
skip ufw, go straight to nftables
nft list ruleset | head -4confession: i don't use ufw
ufw is fine. it's training wheels for iptables and it gets a lot of home servers and vps boxes protected that would otherwise sit wide open. but at some point the training wheels start hiding the bike from you. you type ufw allow 22 and something happens behind the curtain, and if you never look behind that curtain you don't actually know what your firewall is doing. nftables is the curtain. let's pull it back.
what nftables actually is
nftables is the modern packet filtering framework in the linux kernel, the replacement for iptables. ufw, and even a lot of iptables setups, are just frontends that generate rules and hand them to the kernel. when you skip the frontend and talk to nftables directly, you see exactly what rules exist, in what order, and what they do to traffic. no translation layer, no guessing.
nft list ruleset | head -4
this one command dumps your entire active firewall configuration and shows you the first 4 lines. that's it. no flags to memorize, no gui, no "simplified" mode standing between you and the truth of what's protecting your box.
breaking down the command
nft is the nftables command line tool. list ruleset tells it to print every table, chain, and rule currently loaded in the kernel, formatted the way you'd actually write it in a config file. that last part matters: the output isn't a summary, it's valid nftables syntax you could copy straight into a file and reload. | head -4 just trims the output to the first 4 lines so you're not scrolling through a wall of text on a live stream or a reel. drop the pipe and run nft list ruleset on your own machine to see the whole thing.
a typical top few lines look something like this:
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
that's already telling you something real: the default policy on incoming traffic is drop, and it explicitly allows traffic that belongs to a connection you already started. if your output says policy accept instead of policy drop, that's worth stopping and thinking about, because it means anything not explicitly blocked is allowed in.
why this matters for defenders
ufw's job is to make firewall rules easy to write. it is not designed to make them easy to audit. when you're checking your own exposure, or reviewing a server you inherited from someone else, "easy to write" isn't what you need, you need to see ground truth. running nft list ruleset shows you every chain, every hook, every policy, in the actual order the kernel evaluates them. that order matters a lot, a rule sitting after a broad accept rule might never even get evaluated.
this is also how you catch drift. maybe a docker install quietly added its own nftables rules that punch holes ufw doesn't know about. maybe an old rule from a project six months ago is still sitting there accepting traffic on a port you forgot existed. ufw's frontend view won't always surface that. the raw ruleset will.
how to check your own box right now
if you're running ubuntu, debian, fedora, or basically any modern distro, nftables is probably already the backend even if you've been managing it through ufw or firewalld this whole time. run the full command with no filter:
sudo nft list ruleset
read it top to bottom. look for the default policy on the input chain. look for any accept rule that's broader than you intended. compare it against what you think you configured through ufw. if something surprises you, that's the whole point of this exercise, better to be surprised on your own terms than find out from a log later.
the takeaway
frontends like ufw are useful, but they're an abstraction, and abstractions can hide reality from you if you never check underneath them. you don't have to abandon ufw to benefit from this, just run nft list ruleset on your own systems every now and then and actually read what it says. knowing what your firewall is really doing, not what you assume it's doing, is one of the cheapest security wins you'll get all week.