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

i finally moved a box from iptables to nftables

Porting a working iptables ruleset to nftables on a Debian Buster box, and why the new syntax made the rules readable for once.

A terminal showing a firewall ruleset

I've been meaning to do this for years and kept not doing it, because the iptables rules I had worked, and "works" is a strong argument against effort. But Buster ships nftables as the default backend now, and the writing is on the wall, so I bit the bullet on a low-stakes box.

The thing that surprised me is how much more readable the rules are. With iptables you have four tables, a pile of chains, and an ordering you have to hold in your head. nftables collapses that into one syntax where a ruleset actually reads like a description of intent:

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
  }
}

That tcp dport { 22, 80, 443 } set, in one line, would have been three separate iptables rules plus an ipset if I was feeling clever. And inet means the same ruleset covers IPv4 and IPv6, which alone justifies the move; I have lost real time to v6 rules silently not matching because I forgot ip6tables exists.

iptables-translate got me most of the way for the fiddly bits. I'd suggest translating, then rewriting by hand, because the machine translation is correct but ugly. It's worth doing properly while you're in there.