Build a Safe Bridge Firewall Rule with ebtables-nft
You will finish with a small Ethernet bridge rule that drops frames from one named bridge port, displays the rule and its counters, then removes it cleanly. The examples target ebtables-nft 1.8.10 (nf_tables), supplied here by the iptables 1.8.10-3ubuntu2 package.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 15 minutes, plus time to identify the correct bridge interface and MAC address. You need a shell, the installed ebtables-nft command and root privileges for table access. The inspection commands are read-only; appending a rule changes live packet handling and must be treated as a service-disrupting operation.
1. Identify the bridge port and the rule table
First gather the names you will use. The command below is from the separate ip utility, not from ebtables:
$ ip link show
$ ip link show master BRIDGE_NAME
Replace BRIDGE_NAME with the real bridge device, such as br0. The second command lists interfaces enslaved to that bridge. Do not copy an example port name until you have confirmed it on this host. A typo here can make a test rule appear inactive, while selecting the wrong port can cut off legitimate traffic.
Ebtables has three tables. filter is the default and contains INPUT, OUTPUT and FORWARD. nat is for MAC address changes around forwarding, and broute has the early BROUTING chain. This guide uses only the default filter table and its FORWARD chain, where bridged frames are filtered.
2. Save a readable baseline
Listing is a privileged read because the nftables-backed command must fetch the kernel rule set:
$ sudo ebtables-nft -L --Ln --Lc
Bridge table: filter
Bridge chain: INPUT, entries: 0, policy: ACCEPT
Bridge chain: FORWARD, entries: 0, policy: ACCEPT
Bridge chain: OUTPUT, entries: 0, policy: ACCEPT
Your output will differ if rules already exist, and the exact formatting is not a stable interface for scripts. --Ln adds rule numbers, while --Lc prints packet and byte counters. If the command reports permission denied, rerun it with sudo. Do not work around an unexpected existing policy by flushing it.
For a reloadable representation, use the command form produced by --Lx:
$ sudo ebtables-nft -L --Lx
Keep that output in a root-readable temporary file if you need a record for recovery. The manpage documents --Lx as output that reconstructs the table, including user-defined chains. It is a snapshot, not a transaction, so capture it immediately before any planned change.
3. Add one narrowly scoped test rule
Before changing state, decide exactly what should match. This example drops IPv4 Ethernet frames arriving through one bridge port and going to one destination MAC address:
$ sudo ebtables-nft -A FORWARD \
-i BRIDGE_PORT \
-p IPv4 \
-d 02:00:00:00:00:42 \
-j DROP
Replace BRIDGE_PORT and the example MAC address with values you have verified. -A appends to the selected chain. -i matches the physical bridge port receiving the frame, -p IPv4 restricts the rule to IPv4 Ethernet frames, and -d matches the Ethernet destination address. The target DROP discards matching frames. Other Ethernet protocols and other destinations continue through the chain.
There is no dry-run switch in the documented command set. If a rule is wrong, it becomes live as soon as the command succeeds. Keep a management path that does not depend on the affected bridge, and plan an undo command before pressing Enter.
Checkpoint
Immediately list the numbered chain:
$ sudo ebtables-nft -L FORWARD --Ln --Lc
Bridge chain: FORWARD, entries: 1, policy: ACCEPT
1. -i BRIDGE_PORT -p IPv4 -d 02:00:00:00:00:42 -j DROP, pcnt = 0 -- bcnt = 0
The presentation may use protocol names or slightly different spacing. The useful checks are that the rule is in FORWARD, its match values are right, and the counters start at zero. A zero counter means no frame has matched since the rule was added; it does not prove that the rule is incorrect.
4. Observe traffic without guessing
Run the same listing after a controlled test from a permitted host:
$ sudo ebtables-nft -L FORWARD --Ln --Lc
The matching rule's packet counter, shown as pcnt, and byte counter, shown as bcnt, should increase when frames match. If they remain at zero, check the physical port, destination MAC, protocol and chain. A frame destined for the bridge itself belongs to INPUT, while a locally generated frame belongs to OUTPUT; those paths do not match this FORWARD rule.
To reset counters after recording a measurement, use the combined list and zero operation:
$ sudo ebtables-nft -L FORWARD --Ln --Lc -Z
This prints the counters before setting them to zero. Counter changes do not remove or alter the rule. Avoid resetting counters used by another operator's monitoring without agreeing on the measurement window.
5. Remove the test rule and recover
Removal is another live change. If the rule is still number 1 and the chain has not changed, delete it by number:
$ sudo ebtables-nft -D FORWARD 1
$ sudo ebtables-nft -L FORWARD --Ln --Lc
Numbered deletion is easy to misuse after another rule has been inserted. For a shared or changing table, list it first and confirm the number immediately before deletion. The manpage also permits deleting by specifying the complete rule, which removes the first matching rule:
$ sudo ebtables-nft -D FORWARD \
-i BRIDGE_PORT \
-p IPv4 \
-d 02:00:00:00:00:42 \
-j DROP
Verify that the rule is absent. If the original table had a non-default policy or other rules, do not use -F as a shortcut: flushing removes all rules from the selected chain, or every chain when no chain is named, and it does not change the chain policy. Likewise, --init-table replaces the current table data and is not an undo button unless your recorded baseline is known to be the intended initial state.
Deleting a rule does not restore traffic that another rule still drops, nor does it undo a separate change in nat or broute. If you changed a policy or created a user-defined chain during a larger task, reverse those changes explicitly. A user-defined chain cannot be deleted while rules still jump to it.
6. Know the boundaries before expanding the rule
Use --help to inspect extension names available from this userspace program:
$ ebtables-nft -h list_extensions
Match extensions are loaded dynamically by the ebtables userspace tool, so the syntax does not use iptables' separate -m option. Common documented matches include source and destination MAC addresses, interface names, ARP fields, IPv4 and IPv6 fields, VLAN tags, STP fields, packet type and rate limits. Build one match at a time and check its listing before combining several conditions.
The nft-based build does not implement the old atomic options such as --atomic-save and --atomic-commit, and the supplied manpage says the string match is unsupported. Do not copy a legacy ebtables script and assume those features exist. For a persistent deployment, store and review a complete --Lx representation using the host's normal firewall configuration process, then test restoration separately.
Done means
- You confirmed the bridge port and destination MAC from this host.
- You captured the existing table before changing it.
- The rule is in the intended chain and has the intended match fields.
- You checked
pcntandbcntafter controlled traffic. - You removed the temporary rule and confirmed it is absent.
- You did not flush unrelated rules or rely on unsupported atomic options.