Filtering ARP traffic with Linux arptables
Filtering ARP traffic with Linux arptables
Most Linux system administrators will be familiar with iptables on Linux. Less known is the arptables utility, which controls filtering arp packets.
Installation
The arptables utility is easy to set-up, as the main functionality is already implemented in the Linux kernel. Just install the arptables package on your favorite Linux distribution.
Red Hat / CentOS / Fedora
yum install arptables
Debian / Ubuntu
apt-get install arptables
Configuration example
To show the effect of filtering traffic, we will show an example by filtering router traffic and blocking it. This way we won’t be able to connect to the internet.
With the arp command we can query the current list of known ARP addresses.
root@ubuntu:/data# arp Address HWtype HWaddress Flags Mask Iface System.cisofy.com ether 00:a7:22:23:d1:f3 C eth0 Router.cisofy.com ether d8:d7:21:22:5a:8d C eth0
Arptables can block traffic by filtering out the IP. So let’s query the arp list again, now in numeric format.
root@ubuntu:/data# arp -n Address HWtype HWaddress Flags Mask Iface 192.168.1.20 ether 00:a7:22:23:d1:f3 C eth0 192.168.1.1 ether d8:d7:21:22:5a:f4 C eth0
Time to block the router (192.168.1.1):
root@ubuntu:/data# arptables -A INPUT -s 192.168.1.1 -j DROP
So we dropped traffic to this IP adress, right? Let’s try!
root@ubuntu:/data# ping 192.168.1.1 PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. 64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.645 ms 64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.370 ms ^C --- 192.168.1.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.370/0.507/0.645/0.139 ms
Well, that didn’t work like intended. We dropped ARP related traffic to the IP address, but not on IP level. This is also visible in the arp -n list:
root@ubuntu:/data# arp -n Address HWtype HWaddress Flags Mask Iface 192.168.1.20 ether 00:a7:22:23:d1:f3 C eth0 192.168.1.1 ether d8:d7:21:22:5a:f4 C eth0
So to make this work, we simply have to flush the ARP cache. We delete the related ARP entry:
root@ubuntu:/data# arp -d 192.168.1.1 root@ubuntu:/data# arp -n Address HWtype HWaddress Flags Mask Iface 192.168.1.20 ether 00:a7:22:23:d1:f3 C eth0 192.168.1.1 (incomplete) eth0
The arp utility will show an incomplete entry. It knows that recently some traffic passed by, but the MAC address is unknown.
Let’s ping again:
root@ubuntu:/data# ping 192.168.1.1 PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. From 192.168.1.21 icmp_seq=1 Destination Host Unreachable From 192.168.1.21 icmp_seq=2 Destination Host Unreachable
That looks better!
Specific traffic filtering
Back to our original mission: only allow our router to exchange ARP packets.
root@ubuntu:/data# Block ARP traffic from all machines (default: DENY) arptables -P INPUT DROP
root@ubuntu:/data# Allow router (fixed ARP) arptables -A INPUT --source-mac d8:d7:21:22:5a:f4 -j ACCEPT
All ARP packets are blocked now. Each system which will transmitting traffic will end up as an (incomplete) entry.
Enable all ARP traffic
If we want to allow traffic again:
root@ubuntu:/data# arptables -P INPUT ACCEPT
root@ubuntu:/data# arptables --flush
Flushing the full ARP cache can be done with ip utility:
root@ubuntu:/data# ip -s neighbour flush all
Conclusion
Arptables is a very powerful utility to filter traffic and avoid an unexpected router taking over our connectivity. However, keep in mind that connectivity is not fully blocked. Only ARP traffic is blocked (layer 2/3 on the OSI model). If someone is able to manually add an entry to the ARP table, traffic is able to flow again.
7:36 PM
One hardening trick I like is to turn off ARP completely with:
ip link set dev eth0 arp off
Then add a static ARP entry for the router so you can get to that:
arp -s 10.0.0.2 00:0c:29:c0:94:bf
With this setup you can get to the router on your subnet, but because ARP is disabled, you cannot resolve anything else. This works great for a network of clients that connect outward, but you don’t want them to ever exchange data among each other. It would also prevent anyone from the outside to ‘see’ the clients, as the disabled ARP mechanism would not resolve local MAC addresses.
7:48 PM
Thanks Marcin, that’s a great suggestion for our readers.
8:20 AM
how to receive arp packet from queue to our application. i know ip packet can received using nfqueue but using nfqueue i am not receiving any packet in our application
10:41 PM
hello,
I’m so sorry answering 2 years later but found this looking for improving my firewall filtering rules.
If I follow this guide and allow only the router to work with ARP, internet traffic is then blocked, as you stated at the beginning. As a result I added a rule to allow only my lan network segment to iteract with INPUT chain.
But this doesn’t block malicius (and occasional) friends altering arp table and puting their laptops connected to my wifi as a false router.
Is there any way to block that without blocking internet access?
thanks
7:58 AM
You could set a static ARP entry on your systems?
2:37 AM
I have a dual-homed server. All this command “ip link set dev eth0 arp off”
does is disable my Internet if I use it on eth0 OR
disable my NAT if I put it on eth1.
I don’t get its usefulness…
8:54 PM
It turns off ARP. That is most likely not what you intended. You should not do this if you require ARP to actually work. You should only use it when you properly have configured ARP statically.
1:16 AM
How could broadcast ARP traffic like this be blocked? I have tried arptables with no luck.
19:00:01.936837 ARP, Request who-has 192.168.1.216 tell 192.168.1.1, length 46
Cheers
12:42 PM
What specifically did you try so far?
7:06 PM
How can you filter mac addresses based on arp mask?
4:44 AM
how can I block arp packet traffic by defining a threshold value for the same…..? mean if arp request will go beyond the threshold it gets blocked
8:08 PM
Don’t think you can do that out of the box and need a specific script for that to do the counting.
4:18 AM
Hello, would it be possible to use arptables to do create a one to many static arp entry?
This is my issue: I have a test equipment that simulates thousands of IP addresses mapped to the same MAC. I have a server that’s got a 8000 ARP table limit. Since all the traffic is coming from the same test equipment port the source MAC is always the same, so if I have a way to map a range of IP addresses to the same MAC that might solve my issue.
9:29 PM
Hi. I have tried to filter arp traffic without success. I am using the following rule
for mac in $(awk -F”;” ‘{print $2}’ macs.txt); do
arptables -A INPUT –source-mac $mac -j ACCEPT
done
arptables -A INPUT -j DROP
pd: macs.txt contains the mac addresses of the computers on my local network that I must protect (static mac addresses) included server mac address (eth1/eth0)
14:cc:21:3a:73:32
14:cd:22:3b:75:00
But doesn’t work (block all network)