network-programmingfirewallarpdebian-busternftables

nftables - drop arp traffic on specific bridge


I have basic knowledge in nftables syntax and I am trying to drop all arp traffic that occurs on a Linux bridge.

I am running debian and have several virtual machines which are all connected to one bridge. For a project I need to prevent any kind of ARP traffic but only on this bridge.

I tried something like

table bridge bridge_filter {
        chain forward {
                type filter hook forward priority 0;
                policy accept;

                iifname "tap2*" ether type arp drop;
                oifname "tap2*" ether type arp drop;

                iifname "vmbr1" ether type arp drop;
        }
}

(the virtual machines are automatically connected to the bridge with "tap2*" tap devices") but it doesn't work very well, at least I can still see ARP packets on each virtual machines with tcpdump, both request and reply. I know that the config above may not make sense completely but I couldn't figure out what's the right way.

What is wrong with my config?


Solution

  • I'm not sure if you need to filter ARP traffic between just the VMs or also between the host and the VMs.

    If it's the latter then ARP traffic between the host and the VMs won't be filtered when using the "bridge forward" hook.

    In order to filter unicast ARP traffic between the VMs and the host I think you'll need to also use a chain with the bridge "prerouting" and "postrouting" hooks.

    For example

    table bridge bridge_prerouting_filter {
            chain prerouting {
                    type filter hook prerouting priority 0; policy accept;
                    iifname "tap2*" ether type arp drop;
            }
    }
    
    table bridge bridge_postrouting_filter {
            chain postrouting {
                    type filter hook postrouting priority 0; policy accept;
                    oifname "tap2*" ether type arp drop;
            }
    }
    

    In regards to broadcast ARP traffic, that is going to be harder to selectively filter. I don't know if the "oifname" parameter can be applied to broadcast traffic because the output interface is all interfaces.

    Filtering broadcast ARP traffic is going to be easier on the input side but it's going to be difficult to differentiate between broadcast ARP traffic that's allowed and ARP traffic that's not. There was supposed to be a new netdev "egress" filter in Linux 5.7 that might have been able to be used for this purpose but I think it's been removed.