]> git.proxmox.com Git - pve-firewall.git/blobdiff - src/PVE/Firewall.pm
do not abort if security groups does not exists
[pve-firewall.git] / src / PVE / Firewall.pm
index 88191996ea7f9819f6a8ba84fb0e90cc4e43396f..fd83ba32438ae3787f61a7884eb83a7fb1ee4dc9 100644 (file)
@@ -1243,7 +1243,7 @@ sub ruleset_generate_cmdstr {
                die "invalid security group name '$dest'\n";
            }
        } elsif ($dest =~ m/^${ip_alias_pattern}$/){
-           my $alias = lc($source);
+           my $alias = lc($dest);
            my $e = $cluster_conf->{aliases}->{$alias};
            die "no such alias $dest" if !$e;
            push @cmd, "-d $e->{cidr}";
@@ -1436,7 +1436,12 @@ sub ruleset_chain_add_conn_filters {
 }
 
 sub ruleset_chain_add_input_filters {
-    my ($ruleset, $chain, $options) = @_;
+    my ($ruleset, $chain, $options, $cluster_conf, $loglevel) = @_;
+
+    if ($cluster_conf->{ipset}->{blacklist}){
+       ruleset_addlog($ruleset, $chain, 0, "DROP: ", $loglevel, "-m set --match-set PVEFW-blacklist src");
+       ruleset_addrule($ruleset, $chain, "-m set --match-set PVEFW-blacklist src -j DROP");
+    }
 
     if (!(defined($options->{nosmurfs}) && $options->{nosmurfs} == 0)) {
        ruleset_addrule($ruleset, $chain, "-m conntrack --ctstate INVALID,NEW -j PVEFW-smurfs");
@@ -1471,6 +1476,26 @@ sub ruleset_create_vm_chain {
     }
 }
 
+sub ruleset_add_group_rule {
+    my ($ruleset, $cluster_conf, $chain, $rule, $direction, $action) = @_;
+
+    my $group = $rule->{action};
+    my $group_chain = "GROUP-$group-$direction";
+    if(!ruleset_chain_exist($ruleset, $group_chain)){
+       generate_group_rules($ruleset, $cluster_conf, $group);
+    }
+       
+    if ($direction eq 'OUT' && $rule->{iface_out}) {
+       ruleset_addrule($ruleset, $chain, "-o $rule->{iface_out} -j $group_chain");
+    } elsif ($direction eq 'IN' && $rule->{iface_in}) {
+       ruleset_addrule($ruleset, $chain, "-i $rule->{iface_in} -j $group_chain");
+    } else {
+       ruleset_addrule($ruleset, $chain, "-j $group_chain");
+    }
+
+    ruleset_addrule($ruleset, $chain, "-m mark --mark 1 -j $action");
+}
+
 sub ruleset_generate_vm_rules {
     my ($ruleset, $rules, $cluster_conf, $chain, $netid, $direction, $options) = @_;
 
@@ -1482,18 +1507,8 @@ sub ruleset_generate_vm_rules {
        next if $rule->{iface} && $rule->{iface} ne $netid;
        next if !$rule->{enable};
        if ($rule->{type} eq 'group') {
-           my $group_chain = "GROUP-$rule->{action}-$direction";
-           if(!ruleset_chain_exist($ruleset, $group_chain)){
-               generate_group_rules($ruleset, $cluster_conf, $rule->{action});
-           }
-           ruleset_addrule($ruleset, $chain, "-j $group_chain");
-           if ($direction eq 'OUT'){
-               ruleset_addrule($ruleset, $chain, "-m mark --mark 1 -j RETURN");
-           }else{
-               my $accept = generate_nfqueue($options);
-               ruleset_addrule($ruleset, $chain, "-m mark --mark 1 -j $accept");
-           }
-
+           ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, $direction,
+                                  $direction eq 'OUT' ? 'RETURN' : $in_accept);
        } else {
            next if $rule->{type} ne $lc_direction;
            eval {
@@ -1649,7 +1664,7 @@ sub enable_host_firewall {
     ruleset_addrule($ruleset, $chain, "-i lo -j ACCEPT");
 
     ruleset_chain_add_conn_filters($ruleset, $chain, 'ACCEPT');
-    ruleset_chain_add_input_filters($ruleset, $chain, $options);
+    ruleset_chain_add_input_filters($ruleset, $chain, $options, $cluster_conf, $loglevel);
 
     ruleset_addrule($ruleset, $chain, "-m addrtype --dst-type MULTICAST -j ACCEPT");
     ruleset_addrule($ruleset, $chain, "-p udp -m conntrack --ctstate NEW --dport 5404:5405 -j ACCEPT");
@@ -1660,8 +1675,14 @@ sub enable_host_firewall {
 
     # add host rules first, so that cluster wide rules can be overwritten
     foreach my $rule (@$rules, @$cluster_rules) {
-       next if $rule->{type} ne 'in';
-       ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, undef, $cluster_conf);
+       $rule->{iface_in} = $rule->{iface} if $rule->{iface};
+       if ($rule->{type} eq 'group') {
+           ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 'IN', $accept_action);
+       } elsif ($rule->{type} eq 'in') {
+           ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, 
+                                 undef, $cluster_conf);
+       }
+       delete $rule->{iface_in};
     }
 
     # implement input policy
@@ -1687,8 +1708,14 @@ sub enable_host_firewall {
 
     # add host rules first, so that cluster wide rules can be overwritten
     foreach my $rule (@$rules, @$cluster_rules) {
-       next if $rule->{type} ne 'out';
-       ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, undef, $cluster_conf);
+       $rule->{iface_out} = $rule->{iface} if $rule->{iface};
+       if ($rule->{type} eq 'group') {
+           ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 'OUT', $accept_action);
+       } elsif ($rule->{type} eq 'out') {
+           ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, 
+                                 undef, $cluster_conf);
+       }
+       delete $rule->{iface_out};
     }
 
     # implement output policy
@@ -1701,10 +1728,14 @@ sub enable_host_firewall {
 
 sub generate_group_rules {
     my ($ruleset, $cluster_conf, $group) = @_;
-    die "no such security group '$group'\n" if !$cluster_conf->{groups}->{$group};
 
     my $rules = $cluster_conf->{groups}->{$group};
 
+    if (!$rules) {
+       warn "no such security group '$group'\n";
+       $rules = []; # create empty chain
+    }
+
     my $chain = "GROUP-${group}-IN";
 
     ruleset_create_chain($ruleset, $chain);
@@ -1777,7 +1808,7 @@ sub parse_fw_rule {
            die "unknown action '$action'\n";
        }
     } elsif ($type eq 'group') {
-       die "wrong number of rule elements\n" if scalar(@data) != 3;
+       die "wrong number of rule elements\n" if scalar(@data) > 3;
        die "groups disabled\n" if !$allow_groups;
 
        die "invalid characters in group name\n" if $action !~ m/^${security_group_name_pattern}$/;
@@ -1853,7 +1884,7 @@ sub parse_hostfw_option {
 
     my $loglevels = "emerg|alert|crit|err|warning|notice|info|debug|nolog";
 
-    if ($line =~ m/^(enable|nosmurfs|tcpflags|optimize):\s*(0|1)\s*$/i) {
+    if ($line =~ m/^(enable|nosmurfs|tcpflags):\s*(0|1)\s*$/i) {
        $opt = lc($1);
        $value = int($2);
     } elsif ($line =~ m/^(log_level_in|log_level_out|tcp_flags_log_level|smurf_log_level):\s*(($loglevels)\s*)?$/i) {
@@ -2578,17 +2609,12 @@ sub compile {
 
     ruleset_chain_add_conn_filters($ruleset, "PVEFW-FORWARD", "ACCEPT");
 
-    if ($cluster_conf->{ipset}->{blacklist}){
-       ruleset_addlog($ruleset, "PVEFW-FORWARD", 0, "DROP: ", $loglevel, "-m set --match-set PVEFW-blacklist src");
-       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m set --match-set PVEFW-blacklist src -j DROP");
-    }
-
     ruleset_create_chain($ruleset, "PVEFW-VENET-OUT");
     ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i venet0 -j PVEFW-VENET-OUT");
     ruleset_addrule($ruleset, "PVEFW-INPUT", "-i venet0 -j PVEFW-VENET-OUT");
 
     ruleset_create_chain($ruleset, "PVEFW-FWBR-IN");
-    ruleset_chain_add_input_filters($ruleset, "PVEFW-FWBR-IN", $hostfw_options);
+    ruleset_chain_add_input_filters($ruleset, "PVEFW-FWBR-IN", $hostfw_options, $cluster_conf, $loglevel);
 
     ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-bridged --physdev-in fwln+ -j PVEFW-FWBR-IN");
 
@@ -2596,7 +2622,7 @@ sub compile {
     ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-bridged --physdev-out fwln+ -j PVEFW-FWBR-OUT");
 
     ruleset_create_chain($ruleset, "PVEFW-VENET-IN");
-    ruleset_chain_add_input_filters($ruleset, "PVEFW-VENET-IN", $hostfw_options);
+    ruleset_chain_add_input_filters($ruleset, "PVEFW-VENET-IN", $hostfw_options, $cluster_conf, $loglevel);
 
     ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o venet0 -j PVEFW-VENET-IN");
 
@@ -2618,7 +2644,7 @@ sub compile {
        foreach my $netid (keys %$conf) {
            next if $netid !~ m/^net(\d+)$/;
            my $net = PVE::QemuServer::parse_net($conf->{$netid});
-           next if !$net;
+           next if !$net->{firewall};
            my $iface = "tap${vmid}i$1";
 
            my $macaddr = $net->{macaddr};