[pve-devel] [PATCH firewall 6/7] ipfilter: imiplicitly add the default link local address

Wolfgang Bumiller w.bumiller at proxmox.com
Tue Mar 1 12:20:20 CET 2016


When adding an ipset for a device via the 'ipfilter-net$NUM'
name we now implicitly add the default link local address
based on the device's MAC address and a 'nomatch' entry for
the rest of fe80::/10. This is comparable to an ARP/MAC
filter in IPv4 with the main difference that it explicitly
works at IP level.
---
 src/PVE/Firewall.pm | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 2e2b2f7..7f8fe98 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2972,12 +2972,18 @@ sub generate_std_chains {
 }
 
 sub generate_ipset_chains {
-    my ($ipset_ruleset, $clusterfw_conf, $fw_conf) = @_; #fixme
+    my ($ipset_ruleset, $clusterfw_conf, $fw_conf, $device_ips) = @_; #fixme
 
     foreach my $ipset (keys %{$fw_conf->{ipset}}) {
 
 	my $options = $fw_conf->{ipset}->{$ipset};
 
+	if ($device_ips && $ipset =~ /^ipfilter-(net\d+)$/) {
+	    if (my $ips = $device_ips->{$1}) {
+		$options = [@$options, @$ips];
+	    }
+	}
+
 	# remove duplicates
 	my $nethash = {};
 	foreach my $entry (@$options) {
@@ -3270,6 +3276,18 @@ sub compile_iptables_filter {
     return $ruleset;
 }
 
+sub mac_to_linklocal {
+    my ($macaddr) = @_;
+    my @parts = split(/:/, $macaddr);
+    # The standard link local address uses the fe80::/64 prefix with the
+    # modified EUI-64 identifier derived from the MAC address by flipping the
+    # universal/local bit and inserting FF:FE in the middle.
+    # See RFC 4291.
+    $parts[0] = sprintf("%02x", hex($parts[0]) ^ 0x02);
+    my @meui64 = (@parts[0,1,2], 'ff', 'fe', @parts[3,4,5]);
+    return "fe80::$parts[0]$parts[1]:$parts[2]FF:FE$parts[3]:$parts[4]$parts[5]";
+}
+
 sub compile_ipsets {
     my ($cluster_conf, $vmfw_configs, $vmdata) = @_;
 
@@ -3296,7 +3314,21 @@ sub compile_ipsets {
 	    my $vmfw_conf = $vmfw_configs->{$vmid};
 	    return if !$vmfw_conf;
 
-	    generate_ipset_chains($ipset_ruleset, $cluster_conf, $vmfw_conf);
+	    my $device_ips = {};
+	    foreach my $netid (keys %$conf) {
+		next if $netid !~ m/^net(\d+)$/;
+		my $net = PVE::QemuServer::parse_net($conf->{$netid});
+		next if !$net->{firewall};
+
+		my $macaddr = $net->{macaddr};
+		my $linklocal = mac_to_linklocal($macaddr);
+		$device_ips->{$netid} = [
+		    { cidr => $linklocal },
+		    { cidr => 'fe80::/10', nomatch => 1 }
+		];
+	    }
+
+	    generate_ipset_chains($ipset_ruleset, $cluster_conf, $vmfw_conf, $device_ips);
 	};
 	warn $@ if $@; # just to be sure - should not happen
     }
@@ -3308,12 +3340,26 @@ sub compile_ipsets {
             my $vmfw_conf = $vmfw_configs->{$vmid};
             return if !$vmfw_conf;
 
-            generate_ipset_chains($ipset_ruleset, $cluster_conf, $vmfw_conf);
+	    my $device_ips = {};
+	    foreach my $netid (keys %$conf) {
+		next if $netid !~ m/^net(\d+)$/;
+		my $net = PVE::LXC::parse_lxc_network($conf->{$netid});
+		next if !$net->{firewall};
+
+		my $macaddr = $net->{hwaddr};
+		my $linklocal = mac_to_linklocal($macaddr);
+		$device_ips->{$netid} = [
+		    { cidr => $linklocal },
+		    { cidr => 'fe80::/10', nomatch => 1 }
+		];
+	    }
+
+            generate_ipset_chains($ipset_ruleset, $cluster_conf, $vmfw_conf, $device_ips);
         };
         warn $@ if $@; # just to be sure - should not happen
     }
 
-    generate_ipset_chains($ipset_ruleset, undef, $cluster_conf);
+    generate_ipset_chains($ipset_ruleset, undef, $cluster_conf, undef);
 
     return $ipset_ruleset;
 }
-- 
2.1.4





More information about the pve-devel mailing list