nftables: Modern Linux Firewall
Before changing nftables, make sure you have physical or console access to the server. A misconfigured input chain can block SSH and lock you out.
nftables replaced iptables in the Linux kernel starting with version 3.13. If you’re still writing rules in iptables style, it’s time to reconsider. nftables performs better, has built-in dual-stack IPv4/IPv6 support, and lets you manage the entire ruleset as a whole instead of entering commands one by one.
Why Migrate from iptables
iptables has fundamental design problems. Each table (filter, nat, mangle) is a separate rule set with its own semantics. There is no built-in support for simultaneous IPv4 and IPv6 handling—you end up writing two separate rule sets. Performance degrades with a large number of rules due to linear lookup.
nftables takes a different approach. All protocols work within a single data structure—the ruleset. The kernel compiles rules into efficient lookup structures. Atomic ruleset replacement eliminates race conditions during rule updates.
RHEL 8 and newer redirect iptables to nftables by default. Ubuntu 22.04 and later do the same. Check with update-alternatives --display iptables.
Basic Commands: Viewing and Flushing Rules
The first command to memorize:
Output shows all tables, chains, and rules. Without tables, output is empty—this is normal.
Create a table named filter for packet handling:
inet means the table handles both protocols. For IPv4-only use ip, for IPv6 use ip6.
Add a chain for incoming traffic:
Flags breakdown:
| Flag | Purpose |
|---|---|
type filter | Chain type—packet filtering |
hook input | Attachment point—incoming packets |
priority 0 | Processing order relative to other hooks |
policy accept | Default action—allow everything |
Flush rules in a chain:
Delete an entire table:
Adding and Deleting Rules by Handle
Create several rules and inspect their handles:
Output shows something like:
Handles are hidden by default. To work with specific rules:
The -a flag reveals the handle for each rule. Now you can delete by number:
Handles change whenever you add or delete a rule. If your script modifies the ruleset, save nft -a list ruleset output to a file for tracking.
Add a rule with priority before existing ones—at the chain start:
The add command appends to the end, insert adds at the start. For insertion at a specific position:
Atomic Ruleset Replacement
Adding rules one by one creates a window where some rules are active and others are not yet applied. This is unacceptable for production.
The solution: write the complete ruleset to a file and load it atomically:
/etc/nftables.conf is the standard location across most distributions. Now edit it:
Load it:
flush ruleset clears everything before loading. If you need to append to existing rules, remove this line.
Check without applying:
The -c flag performs syntax validation without changing state. Useful in CI/CD before deployment.
Enable persistence on systemd distros:
nftables.service loads /etc/nftables.conf on boot. After editing the file, systemctl restart nftables applies it.
Forward Chain
If the host is not a router, leave forward empty with a drop policy. When IP forwarding is on, the minimum is established replies plus transit between interfaces:
For debugging, log before the implicit drop:
Logs go to journalctl -k or /var/log/kern.log.
Common Scenarios: Blocking Ports and IPs
Block incoming connection from a specific IP:
Block outgoing to a specific IP:
Block an IP range (CIDR):
Block a port for everyone:
Allow a port only for a specific subnet:
Log dropped packets:
Counters appear in nft list ruleset output—they show packet and byte counts.
NAT via Masquerading
For sharing a single IP with a local network:
Masquerading automatically substitutes the external IP of the interface. For port forwarding NAT:
NAT in nftables works only for IPv4. For IPv6, use stateless NAT66 or routing-level addressing.
iptables-nft Compatibility Mode
Some distributions keep iptables “working” by translating to nftables:
The problem is these are two different worlds. iptables-nft translates commands to nftables, but reverse compatibility does not work. Rules created via iptables will not appear directly in nft list ruleset.
Do not use iptables and nftables simultaneously. The result is unpredictable. Either fully migrate to nftables or stay on iptables. Check current mode: iptables -V shows whether iptables-legacy or iptables-nft is in use.
For migration from iptables, use the iptables-translate utility:
Output: nft add rule ip filter input tcp dport 22 accept. Manual verification of output is mandatory—automatic translation is not perfect.
nftables is not the future—it is the present. If you administer Linux servers, spend an evening on migration. The file /etc/nftables.conf with the complete ruleset is your backup and deployment in one.