]> git.proxmox.com Git - pve-firewall.git/blobdiff - src/PVE/Firewall.pm
verify_rule: correctly set ipversion for aliases
[pve-firewall.git] / src / PVE / Firewall.pm
index adaffad873da635138dda76b96c92275f082adcb..f4b199bdb7281f8ab894cdfd26b194f295e8a2bc 100644 (file)
@@ -37,9 +37,13 @@ eval {
     $have_pve_manager = 1;
 };
 
+my $pve_fw_status_dir = "/var/lib/pve-firewall";
+
+mkdir $pve_fw_status_dir; # make sure this exists
+
 my $security_group_name_pattern = '[A-Za-z][A-Za-z0-9\-\_]+';
 my $ipset_name_pattern = '[A-Za-z][A-Za-z0-9\-\_]+';
-my $ip_alias_pattern = '[A-Za-z][A-Za-z0-9\-\_]+';
+our $ip_alias_pattern = '[A-Za-z][A-Za-z0-9\-\_]+';
 
 my $max_alias_name_length = 64;
 my $max_ipset_name_length = 64;
@@ -1213,6 +1217,16 @@ sub verify_rule {
        $errors->{$param} = $msg if !$errors->{$param};
     };
 
+    my $ipversion;
+    my $set_ip_version = sub {
+       my $vers = shift;
+       if ($vers) {
+           die "detected mixed ipv4/ipv6 adresses in rule\n"
+               if $ipversion && ($vers != $ipversion);
+           $ipversion = $vers;
+       }
+    };
+
     my $check_ipset_or_alias_property = sub {
        my ($name, $expected_ipversion) = @_;
 
@@ -1233,8 +1247,7 @@ sub verify_rule {
                my $e = $fw_conf->{aliases}->{$alias} if $fw_conf;
                $e = $cluster_conf->{aliases}->{$alias} if !$e && $cluster_conf;
 
-               die "detected mixed ipv4/ipv6 adresses in rule\n"
-                   if $expected_ipversion && ($expected_ipversion != $e->{ipversion});
+               &$set_ip_version($e->{ipversion});
            }
        }
     };
@@ -1281,16 +1294,6 @@ sub verify_rule {
        }
     }
 
-    my $ipversion;
-    my $set_ip_version = sub {
-       my $vers = shift;
-       if ($vers) {
-           die "detected mixed ipv4/ipv6 adresses in rule\n"
-               if $ipversion && ($vers != $ipversion);
-           $ipversion = $vers;
-       }
-    };
-
     if ($rule->{proto}) {
        eval { pve_fw_verify_protocol_spec($rule->{proto}); };
        &$add_error('proto', $@) if $@;
@@ -3332,7 +3335,9 @@ sub get_ipset_cmdlist {
        }
     }
 
-    foreach my $chain (sort keys %$ruleset) {
+    # create -v4 and -v6 chains first
+    foreach my $chain (keys %$ruleset) {
+       next if $chain !~ m/-v[46]$/;
        my $stat = $statushash->{$chain};
        die "internal error" if !$stat;
 
@@ -3343,7 +3348,20 @@ sub get_ipset_cmdlist {
        }
     }
 
-    foreach my $chain (sort keys %$ruleset) {
+    # then create list chains which use above -v4 and -v6 chains
+    foreach my $chain (keys %$ruleset) {
+       next if $chain =~ m/-v[46]$/;
+       my $stat = $statushash->{$chain};
+       die "internal error" if !$stat;
+
+       if ($stat->{action} eq 'create') {
+           foreach my $cmd (@{$ruleset->{$chain}}) {
+               $cmdlist .= "$cmd\n";
+           }
+       }
+    }
+
+    foreach my $chain (keys %$ruleset) {
        my $stat = $statushash->{$chain};
        die "internal error" if !$stat;
 
@@ -3360,8 +3378,19 @@ sub get_ipset_cmdlist {
        }
     }
 
-    foreach my $chain (sort keys %$statushash) {
+    # remove unused list chains first
+    foreach my $chain (keys %$statushash) {
        next if $statushash->{$chain}->{action} ne 'delete';
+       next if $chain !~ m/-v[46]$/;
+
+       $delete_cmdlist .= "flush $chain\n";
+       $delete_cmdlist .= "destroy $chain\n";
+    }
+
+    # the remove unused -v4 -v6 chains
+    foreach my $chain (keys %$statushash) {
+       next if $statushash->{$chain}->{action} ne 'delete';
+       next if $chain =~ m/-v[46]$/;
 
        $delete_cmdlist .= "flush $chain\n";
        $delete_cmdlist .= "destroy $chain\n";
@@ -3401,11 +3430,24 @@ sub apply_ruleset {
        }
     }
 
+    my $tmpfile = "$pve_fw_status_dir/ipsetcmdlist1";
+    PVE::Tools::file_set_contents($tmpfile, $ipset_create_cmdlist || '');
+
     ipset_restore_cmdlist($ipset_create_cmdlist);
 
+    $tmpfile = "$pve_fw_status_dir/ip4cmdlist";
+    PVE::Tools::file_set_contents($tmpfile, $cmdlist || '');
+
     iptables_restore_cmdlist($cmdlist);
+
+    $tmpfile = "$pve_fw_status_dir/ip6cmdlist";
+    PVE::Tools::file_set_contents($tmpfile, $cmdlistv6 || '');
+
     ip6tables_restore_cmdlist($cmdlistv6);
 
+    $tmpfile = "$pve_fw_status_dir/ipsetcmdlist2";
+    PVE::Tools::file_set_contents($tmpfile, $ipset_delete_cmdlist || '');
+
     ipset_restore_cmdlist($ipset_delete_cmdlist) if $ipset_delete_cmdlist;
 
     # test: re-read status and check if everything is up to date