Andrew Mercer
on this page

What it is

nftables is the successor to iptables, ip6tables, arptables, and ebtables. One tool (nft) and one kernel framework handle IPv4, IPv6, ARP, and bridge filtering, with atomic ruleset reloads and sets/maps built in. It hooks into the same Netfilter points as iptables. Current Debian, Ubuntu, and RHEL-family releases use it as the real backend, and iptables is a compatibility layer (iptables-nft) over it.

Hooks

Where a chain attaches decides what traffic it sees:

nftables hooks for the ipv4, ipv6 and inet families: prerouting, input, forward, output, postrouting

Base chains name a hook (prerouting, input, forward, output, postrouting), a type (filter, nat, route), and a priority. Traffic runs through chains attached to the same hook in priority order.

Structure: tables, chains, rules

A ruleset is tables containing chains containing rules. The inet family covers both IPv4 and IPv6 in one table, which is usually what you want.

Configuration structure: an inet filter table with an input chain accepting ssh and counting

The same thing built interactively:

sudo nft flush ruleset
sudo nft add table inet filter_it
sudo nft add chain inet filter_it input_stuff '{ type filter hook input priority 0 ; }'
sudo nft add rule inet filter_it input_stuff tcp dport 22 accept
sudo nft add rule inet filter_it input_stuff counter

The quotes and \; matter: an unescaped ; is eaten by the shell. sudo nft list ruleset prints the result in the file format below, which can be saved and reloaded.

Ruleset in file form

table inet filter_it {
    chain input_stuff {
        type filter hook input priority 0; policy accept;
        tcp dport ssh accept
        counter packets 0 bytes 0
        drop
    }
}

Where the config lives

The service loads a ruleset file at boot. Location differs by distro.

Ubuntu / Debian — nftables.service runs /etc/nftables.conf, a script starting with #!/usr/sbin/nft -f:

Ubuntu: nftables.service reads /etc/nftables.conf which flushes the ruleset and defines an inet filter table with input, forward and output chains

Fedora / RHEL — the unit reads /etc/sysconfig/nftables.conf, which includes files under /etc/nftables/:

Fedora: nftables.service reads /etc/sysconfig/nftables.conf which includes files in /etc/nftables/ such as inet-filter, ipv4-nat and ipv6-filter

sudo systemctl enable --now nftables
sudo nft -c -f /etc/nftables.conf        # syntax check without applying
sudo nft -f /etc/nftables.conf           # load
sudo nft list ruleset > /tmp/ruleset.nft # export current state

A small host firewall

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept
        iif lo accept
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept
        tcp dport 22 accept
    }
    chain forward { type filter hook forward priority 0; policy drop; }
    chain output  { type filter hook output priority 0; policy accept; }
}

NAT

table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname "eth0" masquerade
    }
}

Migrating from iptables

sudo iptables-save > rules.v4
iptables-restore-translate -f rules.v4 > rules.nft   # translate
sudo nft -f rules.nft

Translation is mechanical and produces verbose output; review and tidy before adopting. Do not mix native nft rules and iptables-nft rules casually. They share the kernel tables and are easy to confuse when debugging.

Cheat sheet

nft list ruleset
nft list tables
nft add rule inet filter input tcp dport 443 accept
nft -a list chain inet filter input     # -a shows rule handles
nft delete rule inet filter input handle 7
nft flush ruleset