Control ARP Traffic Safely with arptables-nft
One wrong DROP rule in an ARP filter and a host vanishes from the network, so arptables-nft rewards a narrow, deliberate first rule. You will inspect the nft-based filter, add one narrowly scoped rule, confirm its position, then remove it. Allow about fifteen minutes. The examples use arptables-nft from iptables 1.8.10-3ubuntu2, and you need root for table changes and usually for listing the ruleset too.
The route
Jump straight to the step you need, or tick off Done means at the end.
Use a maintenance window for anything touching production, and keep a second administrative path open in case a rule locks you out.
1. Check the installed command
Start with read-only checks. This is the nftables-backed implementation of arptables, not a separate nftables rule editor:
$ command -v arptables-nft
/usr/sbin/arptables-nft
$ arptables-nft --version
arptables v1.8.10 (nf_tables)
$ dpkg-query -W -f='${Package} ${Version}\n' iptables
iptables 1.8.10-3ubuntu2
This build reports one ARP table, named filter. The -t filter argument is optional, but if you use -t at all it must come first. The built-in chains are INPUT for frames destined for this host and OUTPUT for locally generated ones.
2. List the current rules
Listing never changes rules, but reading the kernel ruleset can still need elevated privileges. Ask for line numbers so a later deletion has something stable to reference during this inspection:
$ sudo arptables-nft -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT 0x800 -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Your output may show no rules, different policies or different columns; formatting varies by version. From an unprivileged shell this build errors with something like Could not fetch rule set generation id: Permission denied, which is a privilege problem, not proof the table is empty.
There is no FORWARD chain in this nft-based implementation. ARP forwarding belongs to Linux bridges, and filtering that traffic is the job of the bridge filtering tools the local manual describes, not an invented arptables chain.
3. Add a harmless test rule
For a controlled smoke test, append a rule matching one documentation-only source address on one interface that just continues evaluation. Check the real interface name with ip link before swapping it in for eth0:
$ ip link show
$ sudo arptables-nft -t filter -A INPUT -i eth0 -s 192.0.2.10 -j CONTINUE
192.0.2.10 is reserved for documentation and should never be a real peer address. CONTINUE neither accepts nor drops the frame, it just moves to the next rule, which makes this less disruptive, but it still changes the live kernel ruleset and may bump a counter if matching traffic exists.
Checkpoint
List the chain again and check the rule landed where you expected:
$ sudo arptables-nft -t filter -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 CONTINUE 0x800 -- 192.0.2.10 0.0.0.0/0
A rule showing up in the listing is not proof it matches traffic. Its interface, addresses, opcode and protocol type have to describe the actual ARP frames you mean to inspect.
4. Narrow a rule with ARP fields
Rules can match source or destination IP, source or destination MAC, the interface, hardware length, opcode, hardware type and protocol type. This example matches IPv4 ARP requests arriving on eth0 from one source MAC:
$ sudo arptables-nft -t filter -A INPUT \
-i eth0 \
--source-ip 192.0.2.10 \
--source-mac 02:00:00:00:00:10 \
--opcode 1 \
--proto-type 0x800 \
-j CONTINUE
Opcode 1 is an ARP request, 2 is a reply. The manual lists Ethernet as hardware type 1 and IPv4 as protocol type 0x800. Keep a rule specific enough that it cannot accidentally catch address resolution it was never meant to touch.
The target is what happens after a match: ACCEPT lets the frame through, DROP discards it, CONTINUE moves to the next rule, and RETURN leaves a user-defined chain, which can itself be a target. Understand the existing rule order before adding something restrictive; the first match wins.
5. Remove the test rule
Undo the earlier example by deleting its full rule specification. That is safer than trusting a line number after another administrator or automation has touched the chain:
$ sudo arptables-nft -t filter -D INPUT -i eth0 -s 192.0.2.10 -j CONTINUE
$ sudo arptables-nft -t filter -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
If you have a deliberate change and note its line number immediately before removing it, -D INPUT 1 deletes rule 1, but confirm the listing first. Deleting by number is easy to get wrong once rule order has shifted.
Warning
Do not use -F as a general undo. It flushes every rule in the selected chain, or every chain with none named, leaving the policy itself unchanged. To remove an unused user-defined chain use -X; arptables refuses if anything still references it.
6. Treat policies and persistence separately
-P INPUT ACCEPT, -P INPUT DROP and -P INPUT RETURN change the chain policy, the fallback used when nothing matches, so changing it can disrupt networking immediately. Save the current listing and have a tested rollback ready before you touch one:
$ sudo arptables-nft -t filter -L > /tmp/arptables-before.txt
$ sudo arptables-nft -t filter -P INPUT ACCEPT
$ sudo arptables-nft -t filter -L INPUT
These commands only change the current kernel ruleset. The local arptables-nft manual defines no distribution-wide persistence file or service, so if your system restores firewall rules at boot, use that system's own mechanism and test a reboot separately rather than assuming a successful command survives one.
Done means
- You confirmed the nft-based arptables version and the single
filtertable. - You listed rules with line numbers and understood the current chain policies.
- Any test rule was narrowly matched, used a deliberate target and was removed by its full specification.
- You did not rely on a nonexistent
FORWARDchain in this implementation. - Any policy or
DROPchange has a tested recovery path and a separate persistence plan.