Ramblings of an aging IT geek
← Ramblings of an aging IT geek
linux

nftables instead of iptables, finally

Porting a hand-grown iptables ruleset to a single nftables config file, and why the unified ruleset is the part that actually changed my mind.

A Linux terminal showing a firewall ruleset

I've been meaning to move off iptables for years, and kept not doing it because the iptables rules worked and "if it isn't broken" is a powerful sedative. The thing that finally pushed me was maintaining parallel iptables and ip6tables rulesets that had quietly drifted apart, which is exactly the sort of thing that bites you at the worst moment.

nftables fixes that by giving you one ruleset for both families. You write an inet table and it handles IPv4 and IPv6 together, so the v6 rules can't rot while you're only ever testing v4. That alone justified the move.

The syntax took a day to stop fighting. It reads more like a config file than a sequence of commands, which is the point.

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

That tcp dport { 22, 80, 443 } set is the other small joy. In iptables that's three rules; here it's one line, and sets are first-class so you can update them atomically without flushing the chain. nft -f /etc/nftables.conf loads the whole thing in one transaction, so a syntax error leaves you with the old ruleset rather than half a firewall.

I kept iptables-nft around during the transition, since the compatibility layer means the old commands still work against the new backend, which made testing the migration far less nerve-wracking. The ruleset is now a third of the lines, lives in one file, and I can actually read it back in six months and understand what past-me intended. Should have done it years ago.