Home / Alt manpages / arptables-nft(8)

  • arptables-nft(8)
  • Admin command
  • linux

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.

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 filter table.
  • 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 FORWARD chain in this implementation.
  • Any policy or DROP change has a tested recovery path and a separate persistence plan.