ebtables: add arp filtering
authorAlexandre Derumier <aderumier@odiso.com>
Sun, 10 Mar 2019 07:25:06 +0000 (08:25 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 12 Mar 2019 06:35:56 +0000 (07:35 +0100)
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 <aderumier@odiso.com>
src/PVE/Firewall.pm

index 2125d3b..33f558c 100644 (file)
@@ -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');