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

moving a small firewall from iptables to nftables

Porting a modest host firewall from iptables to nftables, and finding the new ruleset genuinely pleasant to read.

A terminal showing an nftables ruleset

I've finally moved one of my boxes off iptables and onto nftables, and I should have done it sooner. nftables has been the in-tree successor since kernel 3.13 turned up years ago, the tooling's matured, and I'd just never had a strong enough reason to disturb a firewall that worked.

The reason in the end was readability. My iptables ruleset was a wall of -A INPUT -p tcp --dport 22 -j ACCEPT lines plus a separate set of ip6tables rules saying almost exactly the same thing again. Two tools, two families, duplicated everywhere. nftables handles both address families in one table and one set of rules, and the syntax reads like something a human wrote on purpose.

The same intent, in nftables, collapses to this:

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

That inet table covers IPv4 and IPv6 at once, which alone halved my config. Sets like { 22, 80, 443 } mean one rule instead of three. The default policy is right there in the chain definition, not bolted on at the bottom where I'd inevitably forget it.

nft list ruleset shows you the live config in the same syntax you wrote, so what you read is what's loaded. No surprises. The whole port took an evening, most of which was double-checking I hadn't locked myself out of SSH, and the result is a firewall I can actually understand at a glance six months from now. That, more than any feature, is the win.