Skip to content

$ cat ./posts/network/nftables-rulesets-that-read-like-prose.nft

-rw-r--r-- 1.6K #network #nftables #security

nftables rulesets that read like prose

by chris · 2 min read · /network /security


iptables rules accumulate as an append-only log of past incidents. nftables lets you write the whole policy as one declarative file, load it atomically, and diff it in review.

1. The shape of a ruleset

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

table inet filter {
  set admin_nets {
    type ipv4_addr
    flags interval
    elements = { 10.0.0.0/24, 192.168.10.0/24 }
  }

  chain input {
    type filter hook input priority filter; policy drop;

    ct state established,related accept
    ct state invalid drop
    iif lo accept

    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept

    tcp dport 22 ip saddr @admin_nets accept
    tcp dport { 80, 443 } accept

    limit rate 5/minute log prefix "nft-drop: "
  }
}

2. Why atomic loading matters

The whole file is applied in one transaction. Either the new policy is live or the old one is untouched — there is no window where half the rules exist, which is the window that iptables scripts historically locked people out in.

3. Sets instead of repetition

Named sets can be updated without reloading the ruleset, which makes them the right place for anything dynamic:

nft add element inet filter admin_nets { 203.0.113.7 }
nft list set inet filter admin_nets

4. Test before you commit

sudo nft -c -f /etc/nftables.conf   # check syntax, change nothing

Run that in CI against the file in the repository. A firewall that only gets validated by being applied to production is a firewall that will eventually be validated during an outage.

← cd .. fris@linux:~/blog$ man network