]> git.proxmox.com Git - pve-firewall.git/blobdiff - src/PVE/Firewall.pm
fix max ipset name lenght
[pve-firewall.git] / src / PVE / Firewall.pm
index dc8664d19be6fb24e31bdaf5f9467570510671ea..2270ad73eb159bb36699c3e9215c0d632c4cbab4 100644 (file)
@@ -760,7 +760,10 @@ sub local_network {
     return $__local_network;
 }
 
-my $max_iptables_ipset_name_length = 27;
+# ipset names are limited to 31 characters, and we use '_swap' 
+# suffix for atomic update, for example PVEFW-${VMID}-${ipset_name}_swap
+
+my $max_iptables_ipset_name_length = 31 - length("_swap");
 
 sub compute_ipset_chain_name {
     my ($vmid, $ipset_name) = @_;
@@ -1211,6 +1214,46 @@ sub copy_rule_data {
     return $rule;
 }
 
+sub rules_modify_permissions {
+    my ($rule_env) = @_;
+
+    if ($rule_env eq 'host') {
+       return {
+           check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
+       };
+    } elsif ($rule_env eq 'cluster' || $rule_env eq 'group') {
+       return {
+           check => ['perm', '/', [ 'Sys.Modify' ]],
+       };
+    } elsif ($rule_env eq 'vm' ||   $rule_env eq 'ct') {
+       return {
+           check => ['perm', '/vms/{vmid}', [ 'VM.Config.Network' ]],
+       }
+    }
+
+    return undef;
+}
+
+sub rules_audit_permissions {
+    my ($rule_env) = @_;
+
+    if ($rule_env eq 'host') {
+       return {
+           check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
+       };
+    } elsif ($rule_env eq 'cluster' || $rule_env eq 'group') {
+       return {
+           check => ['perm', '/', [ 'Sys.Audit' ]],
+       };
+    } elsif ($rule_env eq 'vm' ||   $rule_env eq 'ct') {
+       return {
+           check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+       }
+    }
+
+    return undef;
+}
+
 # core functions
 my $bridge_firewall_enabled = 0;
 
@@ -1752,11 +1795,7 @@ sub generate_venet_rules_direction {
 
     my $chain = "venet0-$vmid-$direction";
 
-    my $ipfilter_name = compute_ipfilter_ipset_name('venet0');
-    my $ipfilter_ipset = compute_ipset_chain_name($vmid, $ipfilter_name)
-       if $vmfw_conf->{ipset}->{$ipfilter_name};
-
-    ruleset_create_vm_chain($ruleset, $chain, $options, undef, $ipfilter_ipset, $direction);
+    ruleset_create_vm_chain($ruleset, $chain, $options, undef, undef, $direction);
 
     ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $chain, 'venet', $direction);
 
@@ -1802,24 +1841,30 @@ sub generate_tap_rules_direction {
     my $ipfilter_ipset = compute_ipset_chain_name($vmid, $ipfilter_name)
        if $vmfw_conf->{ipset}->{$ipfilter_name};       
 
+    # create chain with mac and ip filter
     ruleset_create_vm_chain($ruleset, $tapchain, $options, $macaddr, $ipfilter_ipset, $direction);
 
-    ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $tapchain, $netid, $direction, $options);
+    if ($options->{enable}) {
+       ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $tapchain, $netid, $direction, $options);
 
-    ruleset_generate_vm_ipsrules($ruleset, $options, $direction, $iface);
+       ruleset_generate_vm_ipsrules($ruleset, $options, $direction, $iface);
 
-    # implement policy
-    my $policy;
+       # implement policy
+       my $policy;
 
-    if ($direction eq 'OUT') {
-       $policy = $options->{policy_out} || 'ACCEPT'; # allow everything by default
-    } else {
+       if ($direction eq 'OUT') {
+           $policy = $options->{policy_out} || 'ACCEPT'; # allow everything by default
+       } else {
        $policy = $options->{policy_in} || 'DROP'; # allow nothing by default
-    }
+       }
 
-    my $accept = generate_nfqueue($options);
-    my $accept_action = $direction eq 'OUT' ? "PVEFW-SET-ACCEPT-MARK" : $accept;
-    ruleset_add_chain_policy($ruleset, $tapchain, $vmid, $policy, $loglevel, $accept_action);
+       my $accept = generate_nfqueue($options);
+       my $accept_action = $direction eq 'OUT' ? "PVEFW-SET-ACCEPT-MARK" : $accept;
+       ruleset_add_chain_policy($ruleset, $tapchain, $vmid, $policy, $loglevel, $accept_action);
+    } else {
+       my $accept_action = $direction eq 'OUT' ? "PVEFW-SET-ACCEPT-MARK" : 'ACCEPT';
+       ruleset_add_chain_policy($ruleset, $tapchain, $vmid, 'ACCEPT', $loglevel, $accept_action);
+    }
 
     # plug the tap chain to bridge chain
     if ($direction eq 'IN') {
@@ -2857,7 +2902,6 @@ sub compile {
            my $conf = $vmdata->{qemu}->{$vmid};
            my $vmfw_conf = $vmfw_configs->{$vmid};
            return if !$vmfw_conf;
-           return if !$vmfw_conf->{options}->{enable};
 
            generate_ipset_chains($ipset_ruleset, $cluster_conf, $vmfw_conf);
 
@@ -2884,32 +2928,34 @@ sub compile {
 
            my $vmfw_conf = $vmfw_configs->{$vmid};
            return if !$vmfw_conf;
-           return if !$vmfw_conf->{options}->{enable};
 
            generate_ipset_chains($ipset_ruleset, $cluster_conf, $vmfw_conf);
 
-           if ($conf->{ip_address} && $conf->{ip_address}->{value}) {
-               my $ip = $conf->{ip_address}->{value};
-               $ip =~ s/\s+/,/g;
-               parse_address_list($ip); # make sure we have a valid $ip list
+           if ($vmfw_conf->{options}->{enable}) {
+               if ($conf->{ip_address} && $conf->{ip_address}->{value}) {
+                   my $ip = $conf->{ip_address}->{value};
+                   $ip =~ s/\s+/,/g;
+                   parse_address_list($ip); # make sure we have a valid $ip list
 
-               my @ips = split(',', $ip);
+                   my @ips = split(',', $ip);
 
-               foreach my $singleip (@ips) {
-                   my $venet0ipset = {};
-                   $venet0ipset->{cidr} = $singleip;
-                   push @{$cluster_conf->{ipset}->{venet0}}, $venet0ipset;
-               }
+                   foreach my $singleip (@ips) {
+                       my $venet0ipset = {};
+                       $venet0ipset->{cidr} = $singleip;
+                       push @{$cluster_conf->{ipset}->{venet0}}, $venet0ipset;
+                   }
 
-               generate_venet_rules_direction($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip, 'IN');
-               generate_venet_rules_direction($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip, 'OUT');
+                   generate_venet_rules_direction($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip, 'IN');
+                   generate_venet_rules_direction($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip, 'OUT');
+               }
            }
 
            if ($conf->{netif} && $conf->{netif}->{value}) {
                my $netif = PVE::OpenVZ::parse_netif($conf->{netif}->{value});
                foreach my $netid (keys %$netif) {
                    my $d = $netif->{$netid};
-
+                   my $bridge = $d->{bridge};
+                   next if !$bridge || $bridge !~ m/^vmbr\d+(v(\d+))?f$/; # firewall enabled ?
                    my $macaddr = $d->{mac};
                    my $iface = $d->{host_ifname};
                    generate_tap_rules_direction($ruleset, $cluster_conf, $iface, $netid, $macaddr,