]> git.proxmox.com Git - pve-firewall.git/blobdiff - src/PVE/Firewall.pm
enable hostfw for ipv4 only
[pve-firewall.git] / src / PVE / Firewall.pm
index dd251bf2edda73d22b34d5de754b8ea97d185862..3123550fb24805e6ee96c4a8613674dc24bc2e6d 100644 (file)
@@ -802,16 +802,28 @@ sub parse_address_list {
 
     my $count = 0;
     my $iprange = 0;
+    my $ipversion;
+
     foreach my $elem (split(/,/, $str)) {
        $count++;
-       if (!Net::IP->new($elem)) {
+       my $ip = Net::IP->new($elem);
+       if (!$ip) {
            my $err = Net::IP::Error();
            die "invalid IP address: $err\n";
        }
        $iprange = 1 if $elem =~ m/-/;
+
+       my $new_ipversion = Net::IP::ip_is_ipv6($ip->ip()) ? 6 : 4;
+
+       die "detected mixed ipv4/ipv6 addresses in address list '$str'\n"
+           if $ipversion && ($new_ipversion != $ipversion);
+
+       $ipversion = $new_ipversion;
     }
 
-    die "you can use a range in a list\n" if $iprange && $count > 1;
+    die "you can't use a range in a list\n" if $iprange && $count > 1;
+
+    return $ipversion;
 }
 
 sub parse_port_name_number_or_range {
@@ -853,8 +865,8 @@ sub pve_fw_verify_port_spec {
    return $portstr;
 }
 
-PVE::JSONSchema::register_format('pve-fw-v4addr-spec', \&pve_fw_verify_v4addr_spec);
-sub pve_fw_verify_v4addr_spec {
+PVE::JSONSchema::register_format('pve-fw-addr-spec', \&pve_fw_verify_addr_spec);
+sub pve_fw_verify_addr_spec {
    my ($list) = @_;
 
    parse_address_list($list);
@@ -953,11 +965,11 @@ my $rule_properties = {
     },
     iface => get_standard_option('pve-iface', { optional => 1 }),
     source => {
-       type => 'string', format => 'pve-fw-v4addr-spec',
+       type => 'string', format => 'pve-fw-addr-spec',
        optional => 1,
     },
     dest => {
-       type => 'string', format => 'pve-fw-v4addr-spec',
+       type => 'string', format => 'pve-fw-addr-spec',
        optional => 1,
     },
     proto => {
@@ -1168,14 +1180,21 @@ sub verify_rule {
            if !$rule->{proto};
     }
 
+    my $ipversion;
+
     if ($rule->{source}) {
-       eval { parse_address_list($rule->{source}); };
+       eval { $ipversion = parse_address_list($rule->{source}); };
        &$add_error('source', $@) if $@;
        &$check_ipset_or_alias_property('source');
     }
 
     if ($rule->{dest}) {
-       eval { parse_address_list($rule->{dest}); };
+       eval { 
+           my $dest_ipversion = parse_address_list($rule->{dest}); 
+           die "detected mixed ipv4/ipv6 adresses in rule\n"
+               if defined($ipversion) && ($dest_ipversion != $ipversion);
+           $ipversion = $dest_ipversion;
+       };
        &$add_error('dest', $@) if $@;
        &$check_ipset_or_alias_property('dest');
     }
@@ -1195,6 +1214,7 @@ sub verify_rule {
     }
 
     $rule->{errors} = $errors if $error_count;
+    $rule->{ipversion} = $ipversion if $ipversion;
 
     return $rule;
 }
@@ -1721,7 +1741,7 @@ sub ruleset_add_group_rule {
 }
 
 sub ruleset_generate_vm_rules {
-    my ($ruleset, $rules, $cluster_conf, $vmfw_conf, $chain, $netid, $direction, $options) = @_;
+    my ($ruleset, $rules, $cluster_conf, $vmfw_conf, $chain, $netid, $direction, $options, $ipversion) = @_;
 
     my $lc_direction = lc($direction);
 
@@ -1730,6 +1750,8 @@ sub ruleset_generate_vm_rules {
     foreach my $rule (@$rules) {
        next if $rule->{iface} && $rule->{iface} ne $netid;
        next if !$rule->{enable} || $rule->{errors};
+       next if $rule->{ipversion} && ($rule->{ipversion} != $ipversion);
+
        if ($rule->{type} eq 'group') {
            ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, $direction,
                                   $direction eq 'OUT' ? 'RETURN' : $in_accept);
@@ -1785,7 +1807,7 @@ sub ruleset_generate_vm_ipsrules {
 }
 
 sub generate_venet_rules_direction {
-    my ($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip, $direction) = @_;
+    my ($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip, $direction, $ipversion) = @_;
 
     my $lc_direction = lc($direction);
 
@@ -1798,7 +1820,7 @@ sub generate_venet_rules_direction {
 
     ruleset_create_vm_chain($ruleset, $chain, $options, undef, undef, $direction);
 
-    ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $chain, 'venet', $direction);
+    ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $chain, 'venet', $direction, undef, $ipversion);
 
     # implement policy
     my $policy;
@@ -1827,7 +1849,7 @@ sub generate_venet_rules_direction {
 }
 
 sub generate_tap_rules_direction {
-    my ($ruleset, $cluster_conf, $iface, $netid, $macaddr, $vmfw_conf, $vmid, $direction) = @_;
+    my ($ruleset, $cluster_conf, $iface, $netid, $macaddr, $vmfw_conf, $vmid, $direction, $ipversion) = @_;
 
     my $lc_direction = lc($direction);
 
@@ -1846,7 +1868,7 @@ sub generate_tap_rules_direction {
     ruleset_create_vm_chain($ruleset, $tapchain, $options, $macaddr, $ipfilter_ipset, $direction);
 
     if ($options->{enable}) {
-       ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $tapchain, $netid, $direction, $options);
+       ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf, $vmfw_conf, $tapchain, $netid, $direction, $options, $ipversion);
 
        ruleset_generate_vm_ipsrules($ruleset, $options, $direction, $iface);
 
@@ -2903,7 +2925,7 @@ sub compile_iptables_filter {
 
     my $ipset_ruleset = {};
 
-    if ($hostfw_enable) {
+    if ($hostfw_enable && $ipversion eq 4) {
        eval { enable_host_firewall($ruleset, $hostfw_conf, $cluster_conf); };
        warn $@ if $@; # just to be sure - should not happen
     }
@@ -2927,9 +2949,9 @@ sub compile_iptables_filter {
 
                my $macaddr = $net->{macaddr};
                generate_tap_rules_direction($ruleset, $cluster_conf, $iface, $netid, $macaddr,
-                                            $vmfw_conf, $vmid, 'IN');
+                                            $vmfw_conf, $vmid, 'IN', $ipversion);
                generate_tap_rules_direction($ruleset, $cluster_conf, $iface, $netid, $macaddr,
-                                            $vmfw_conf, $vmid, 'OUT');
+                                            $vmfw_conf, $vmid, 'OUT', $ipversion);
            }
        };
        warn $@ if $@; # just to be sure - should not happen
@@ -2949,18 +2971,20 @@ sub compile_iptables_filter {
                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 = ();
 
-                   foreach my $singleip (@ips) {
-                       my $venet0ipset = {};
-                       $venet0ipset->{cidr} = $singleip;
-                       push @{$cluster_conf->{ipset}->{venet0}}, $venet0ipset;
+                   foreach my $singleip (split(',', $ip)) {
+                       my $singleip_ver = parse_address_list($singleip); # make sure we have a valid $ip list
+                       push @{$cluster_conf->{ipset}->{venet0}}, { cidr => $singleip };
+                       push @ips, $singleip if $singleip_ver == $ipversion;
                    }
 
-                   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 (scalar(@ips)) {
+                       my $ip_list = join(',', @ips);
+                       generate_venet_rules_direction($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip_list, 'IN', $ipversion);
+                       generate_venet_rules_direction($ruleset, $cluster_conf, $vmfw_conf, $vmid, $ip_list, 'OUT', $ipversion);
+                   }
                }
            }
 
@@ -2973,9 +2997,9 @@ sub compile_iptables_filter {
                    my $macaddr = $d->{mac};
                    my $iface = $d->{host_ifname};
                    generate_tap_rules_direction($ruleset, $cluster_conf, $iface, $netid, $macaddr,
-                                                $vmfw_conf, $vmid, 'IN');
+                                                $vmfw_conf, $vmid, 'IN', $ipversion);
                    generate_tap_rules_direction($ruleset, $cluster_conf, $iface, $netid, $macaddr,
-                                                $vmfw_conf, $vmid, 'OUT');
+                                                $vmfw_conf, $vmid, 'OUT', $ipversion);
                }
            }
        };