SynologyRS
Networking

A no-nonsense nftables firewall for a single host

📅 2024-12-14✎ 8 min read

One stateful ruleset that covers 95% of what a small server needs.

I migrated off ufw to nftables because I wanted to read the actual ruleset and tweak it without a wrapper guessing what I meant. One stateful set covers almost everything a small server needs. Everything else is policy.

The shape of it

Default-deny inbound, default-allow outbound, allow loopback, allow established connections, and then a short allow-list for what you publish. Stateful filtering does most of the heavy lifting for free.

table inet filter {
    chain input {
        type filter hook input priority 0;
        ct state established,related accept
        ct state invalid drop
        iif lo accept
        tcp dport { 22, 443 } accept
        log level warning
        drop
    }
}

Logging the drops

Add a final log-and-drop so you can see what got rejected. A quiet drop is safe; a logged drop is useful. I rate-limit the logging so a scan storm does not fill the disk.

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

Make it survive reboot

Save the ruleset and restore it on boot, or use the nft systemd unit. A firewall that only exists until the next restart is a hobby.

If you cannot read your firewall ruleset out loud, you do not have a firewall — you have a hope.