X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=83915df8728720eb9ce3177461699510a29efb71;hb=ff5d050e12644e08eafdcd3b476fee7a9f38beaf;hp=a69583bbbd95cbedac25189a92c23aec4f242ee2;hpb=593604ccccc1bce3b83c58db6eafcedac40a94d4;p=pve-firewall.git diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index a69583b..83915df 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -135,6 +135,12 @@ my $pve_ipv6fw_macros = { 'Ping' => [ { action => 'PARAM', proto => 'icmpv6', dport => 'echo-request' }, ], + 'NeighborDiscovery' => [ + "IPv6 neighbor solicitation, neighbor and router advertisement", + { action => 'PARAM', proto => 'icmpv6', dport => 'router-advertisement' }, + { action => 'PARAM', proto => 'icmpv6', dport => 'neighbor-solicitation' }, + { action => 'PARAM', proto => 'icmpv6', dport => 'neighbor-advertisement' }, + ], 'Trcrt' => [ { action => 'PARAM', proto => 'udp', dport => '33434:33524' }, { action => 'PARAM', proto => 'icmpv6', dport => 'echo-request' }, @@ -500,6 +506,7 @@ my $pve_fw_macros = { my $pve_fw_parsed_macros; my $pve_fw_macro_descr; +my $pve_fw_macro_ipversion = {}; my $pve_fw_preferred_macro_names = {}; my $pve_std_chains = {}; @@ -749,14 +756,32 @@ sub init_firewall_macros { $pve_fw_parsed_macros = {}; - foreach my $k (keys %$pve_fw_macros) { + my $parse = sub { + my ($k, $macro) = @_; my $lc_name = lc($k); - my $macro = $pve_fw_macros->{$k}; - if (!ref($macro->[0])) { - $pve_fw_macro_descr->{$k} = shift @$macro; + $pve_fw_macro_ipversion->{$k} = 0; + while (!ref($macro->[0])) { + my $desc = shift @$macro; + if ($desc eq 'ipv4only') { + $pve_fw_macro_ipversion->{$k} = 4; + } elsif ($desc eq 'ipv6only') { + $pve_fw_macro_ipversion->{$k} = 6; + } else { + $pve_fw_macro_descr->{$k} = $desc; + } } $pve_fw_preferred_macro_names->{$lc_name} = $k; $pve_fw_parsed_macros->{$k} = $macro; + }; + + foreach my $k (keys %$pve_fw_macros) { + &$parse($k, $pve_fw_macros->{$k}); + } + + foreach my $k (keys %$pve_ipv6fw_macros) { + next if $pve_fw_parsed_macros->{$k}; + &$parse($k, $pve_ipv6fw_macros->{$k}); + $pve_fw_macro_ipversion->{$k} = 6; } } @@ -874,14 +899,20 @@ sub local_network { my $testip = Net::IP->new($ip); - my $routes = PVE::ProcFSTools::read_proc_net_route(); + my $isv6 = $testip->version == 6; + my $routes = $isv6 ? PVE::ProcFSTools::read_proc_net_ipv6_route() + : PVE::ProcFSTools::read_proc_net_route(); foreach my $entry (@$routes) { - my $mask = $ipv4_mask_hash_localnet->{$entry->{mask}}; - next if !defined($mask); - return if $mask eq '0.0.0.0'; + my $mask; + if ($isv6) { + $mask = $entry->{prefix}; + } else { + $mask = $ipv4_mask_hash_localnet->{$entry->{mask}}; + next if !defined($mask); + } my $cidr = "$entry->{dest}/$mask"; my $testnet = Net::IP->new($cidr); - if ($testnet->overlaps($testip)) { + if ($testnet->overlaps($testip) == $Net::IP::IP_B_IN_A_OVERLAP) { $__local_network = $cidr; return; } @@ -1165,6 +1196,11 @@ my $apply_macro = sub { $macro_rules = $pve_ipv6fw_macros->{$macro_name}; } + # skip macros which are specific to another ipversion + if ($ipversion && (my $required = $pve_fw_macro_ipversion->{$macro_name})) { + return if $ipversion != $required; + } + my $rules = []; foreach my $templ (@$macro_rules) { @@ -2924,8 +2960,7 @@ sub generate_ipset_chains { } #http://backreference.org/2013/03/01/ipv6-address-normalization/ if ($ver == 6) { - my $ipv6 = inet_pton(AF_INET6, lc($cidr)); - $cidr = inet_ntop(AF_INET6, $ipv6); + $cidr = lc(Net::IP::ip_compress_address($cidr, 6)); $cidr =~ s|/128$||; } else { $cidr =~ s|/32$||;