From 401c141b36315dbbfaf88b293a44654a8610793b Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Sun, 10 Mar 2019 08:25:06 +0100 Subject: [PATCH] ebtables: add arp filtering This implemented arp filtering if ipfilter is enable https://bugzilla.proxmox.com/show_bug.cgi?id=2125 They are another filters possible (ipv4,rarp), i don't known if we need them. Signed-off-by: Alexandre Derumier --- src/PVE/Firewall.pm | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 2125d3b..33f558c 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -3687,6 +3687,7 @@ sub compile_ebtables_filter { my $conf = $vmdata->{qemu}->{$vmid}; my $vmfw_conf = $vmfw_configs->{$vmid}; return if !$vmfw_conf; + my $ipsets = $vmfw_conf->{ipset}; foreach my $netid (sort keys %$conf) { next if $netid !~ m/^net(\d+)$/; @@ -3694,9 +3695,15 @@ sub compile_ebtables_filter { next if !$net->{firewall}; my $iface = "tap${vmid}i$1"; my $macaddr = $net->{macaddr}; - - generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid); - + my $arpfilter = []; + if (defined(my $ipset = $ipsets->{"ipfilter-$netid"})) { + foreach my $ipaddr (@$ipset) { + my($ip, $version) = parse_ip_or_cidr($ipaddr->{cidr}); + next if !$ip || ($version && $version != 4); + push(@$arpfilter, $ip); + } + } + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter); } }; warn $@ if $@; # just to be sure - should not happen @@ -3709,6 +3716,7 @@ sub compile_ebtables_filter { my $vmfw_conf = $vmfw_configs->{$vmid}; return if !$vmfw_conf || !$vmfw_conf->{options}->{enable}; + my $ipsets = $vmfw_conf->{ipset}; foreach my $netid (sort keys %$conf) { next if $netid !~ m/^net(\d+)$/; @@ -3716,7 +3724,16 @@ sub compile_ebtables_filter { next if !$net->{firewall}; my $iface = "veth${vmid}i$1"; my $macaddr = $net->{hwaddr}; - generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid); + my $arpfilter = []; + if (defined(my $ipset = $ipsets->{"ipfilter-$netid"})) { + foreach my $ipaddr (@$ipset) { + my($ip, $version) = parse_ip_or_cidr($ipaddr->{cidr}); + next if !$ip || ($version && $version != 4); + push(@$arpfilter, $ip); + } + } + push(@$arpfilter, $net->{ip}) if $net->{ip} && $vmfw_conf->{options}->{ipfilter}; + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter); } }; warn $@ if $@; # just to be sure - should not happen @@ -3726,7 +3743,7 @@ sub compile_ebtables_filter { } sub generate_tap_layer2filter { - my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid) = @_; + my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter) = @_; my $options = $vmfw_conf->{options}; my $tapchain = $iface."-OUT"; @@ -3741,6 +3758,17 @@ sub generate_tap_layer2filter { ruleset_addrule($ruleset, $tapchain, "-s ! $macaddr", '-j DROP'); } + if (@$arpfilter){ + my $arpchain = $tapchain."-ARP"; + ruleset_addrule($ruleset, $tapchain, "-p ARP", "-j $arpchain"); + ruleset_create_chain($ruleset, $arpchain); + + foreach my $ip (@{$arpfilter}) { + ruleset_addrule($ruleset, $arpchain, "-p ARP --arp-ip-src $ip", '-j RETURN'); + } + ruleset_addrule($ruleset, $arpchain, '', '-j DROP'); + } + if (defined($options->{layer2_protocols})){ foreach my $proto (split(/,/, $options->{layer2_protocols})) { ruleset_addrule($ruleset, $tapchain, "-p $proto", '-j ACCEPT'); -- 2.39.2