What nftables is and why it beats iptables
nftables is a packet filtering framework in the Linux kernel that, starting with Linux 3.13, has gradually replaced iptables, ipset, and ip6tables. On Debian 10+, Ubuntu 20.04+, and most modern distributions, nftables is used by default, and the iptables command translates rules into nftables through the compatible iptables-nft layer.
The main advantages: a single syntax for IPv4 and IPv6 instead of separate iptables and ip6tables commands, atomic loading of the entire ruleset with no intermediate states, built-in sets instead of a separate ipset tool, and a compact, readable rule format.
Installing nftables and migrating from iptables
Checking the current backend:
nft --version
iptables --version
The string nf_tables in the output of iptables --version means iptables is already running on the nftables backend. Install the package where it's missing:
apt install -y nftables
systemctl enable --now nftables
Before migrating, it helps to save the current iptables rules so you don't lose access to the server — especially on a server set up following the guide on securing sshd_config with a non-standard SSH port.
Rule structure: tables, chains, rules
nftables organizes rules into three levels: a table is tied to an address family (ip, ip6, inet), a chain defines a packet interception point (input, forward, output), and rules inside a chain run in order.
| Element | Purpose |
|---|---|
| table | a container for chains of one address family |
| chain | a packet processing point: input, output, forward |
| rule | a condition and action: accept, drop, reject |
| set | a named group of values — ports or addresses |
The inet family combines IPv4 and IPv6 in one table, which is more compact than maintaining two parallel configurations.
Basic nftables firewall setup
The configuration usually lives in /etc/nftables.conf. An example of a basic ruleset: allow the loopback interface, established connections, SSH, and HTTP/HTTPS, and reject the rest of the inbound traffic.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif "lo" accept
ct state established,related accept
tcp dport 22 accept
tcp dport { 80, 443 } accept
ip protocol icmp accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Applying the ruleset:
nft -f /etc/nftables.conf
The same logic is used by UFW, which is a front end for nftables — the basic principles are covered in the article on setting up the UFW firewall.
Useful commands for troubleshooting
The main commands for viewing and debugging rules:
nft list ruleset
nft list table inet filter
nft list chain inet filter input
nft delete rule inet filter input handle 5
nft list ruleset prints every active rule in every table, and handle in the last command is the id of a specific rule, found with the -a flag: nft -a list chain inet filter input.
Autostart and persisting rules
The /etc/nftables.conf file is loaded by the systemd service at server boot:
systemctl enable nftables
systemctl restart nftables
Rules added directly in the terminal with nft add rule are not saved after a reboot — they must be written into the configuration file. Fail2ban can also work with the nftables backend — see the article on setting up Fail2Ban.
Summary: a checklist for moving to nftables
- Check the current backend: the string
nf_tablesiniptables --versionconfirms the migration. - The main rule levels are table → chain → rule; the
inetfamily combines IPv4 and IPv6. - Store rules in
/etc/nftables.confand apply them withnft -f. - Use
nft list rulesetandnft -a list chainfor debugging. - Keep a backup SSH session open before applying new rules — a mistake in the input chain blocks access.