Learning how to use nftables in Linux stopped being optional somewhere around 2020, but most of us only figured that out when something broke. I personally discovered it the hard way on my homelab Proxmox host. I’d just dist-upgraded to Debian 12, ran my muscle-memory iptables -L to check my rules, and stared at totally empty chains. My brain did that little freeze thing. Was I hacked? Did my rules wipe? Nope. nftables had quietly become the default backend, and the old iptables command was now a thin compatibility shim talking to a different engine underneath.

That confusion sent me down a weekend-long rabbit hole, and honestly? I came out the other side a convert. nftables is faster, cleaner, more atomic, and way less of a footgun than iptables once you understand its model. So let’s walk through it — what it is, how the pieces fit together, and how to build a real working firewall from scratch.
Quick answer: what is nftables?
nftables is the modern Linux kernel firewall framework that replaces iptables, ip6tables, arptables, and ebtables with a single unified tool called nft. It supports IPv4 and IPv6 in one ruleset, performs atomic rule swaps with no protection gaps, and uses sets for O(1) lookups instead of iptables-style linear scanning. It’s the default firewall backend on Debian 10+, Ubuntu 20.04+, RHEL 8+, and Fedora.
What Is nftables (And Why It’s Replacing iptables)
nftables landed in the mainline Linux kernel back in version 3.13 (2014), authored by Patrick McHardy as the officially-blessed successor to iptables. For years it sat alongside iptables while distros worked out migration paths. Then around 2019 the switchover started in earnest. By 2026, nftables is the active kernel backend on roughly 70-75% of Linux server installations — and that number keeps climbing as old RHEL 7 boxes finally die off. If you want the longer historical view, the nftables background and history page on Wikipedia is a solid primer.
Get a VPS from as low as $11/year! WOW!
The selling points are pretty compelling once you’ve used both:
- One tool to rule them all: nftables unifies iptables, ip6tables, arptables, and ebtables into the single
nftcommand. No more parallel rulesets for IPv4 and IPv6. - Atomic updates: iptables had to read, modify, and re-upload the ruleset, which left tiny protection gaps during edits. nftables swaps rulesets in one kernel operation.
- Real performance: nftables compiles rules into bytecode that runs on the kernel’s
nf_tablesVM. Sets give you O(1) lookups for IP matching, instead of iptables’ linear O(n) scanning. - The inet family: A single rule covers both IPv4 and IPv6 traffic. Coming from maintaining duplicate
iptables/ip6tablesconfigs, this alone is worth the switch.
If you’re migrating from the old tool and want to brush up on the model you’re leaving behind, our iptables guide is a good side-by-side companion to this one.
“nftables replaces all of these tools [iptables, ip6tables, arptables, ebtables] with a single unified framework, allowing administrators to manage all address families using one consistent system.” — Red Hat nftables documentation
And it’s not just a small-server story. Kubernetes flipped kube-proxy to nftables mode in early 2025. The Kubernetes nftables kube-proxy benchmark showed that at 30,000 services, nftables’ p99 latency was roughly equivalent to iptables’ best-case p01 latency. That’s a wild number. It means nftables stays predictable under load while iptables fell apart.
The nftables Hierarchy: Tables, Chains, and Rules
Here’s the mental model that finally made nftables click for me. Everything lives in a three-level hierarchy: tables hold chains, and chains hold rules. Unlike iptables, there are no built-in tables or chains. You build them all yourself. That feels weird at first, then liberating once you accept it.
Tables: Your Namespace Container
A table is just a named container scoped to an address family. The families you’ll actually use are:
- ip — IPv4 only
- ip6 — IPv6 only
- inet — IPv4 + IPv6 together (use this 95% of the time)
- arp, bridge, netdev — specialized cases for ARP, bridged traffic, and ingress filtering
Chains: Base Chains vs Regular Chains
Chains come in two flavors. Base chains are entry points that hook into the kernel’s network stack — they need a type, a hook (prerouting, input, forward, output, or postrouting), and a priority. Regular chains are just jump targets you build for organization. The base chain hooks line up with where packets are in their journey through the kernel, so input filters traffic destined for the local box, forward handles routed traffic, and so on.
Rules: Expressions and Statements
A rule is a match expression plus an action. Expressions are conditions like tcp dport 22 or ct state established,related. Actions (called verdicts) include accept, drop, queue, continue, return, jump, and goto. That’s basically the whole language, and once you see it written out it reads almost like English.
Installing and Verifying nftables
Most modern distros ship nftables by default, so check first before installing anything:
nft --version
If you get a version number, you’re already done. If not, here’s how to install it:
- Debian / Ubuntu:
sudo apt install nftables - RHEL / Fedora / Rocky:
sudo dnf install nftables - Arch / Manjaro:
sudo pacman -S nftables
Before you start writing rules directly, check what else might already be managing your firewall. Running firewalld or ufw alongside hand-written nftables rules is a fast lane to mysterious behavior — pick one management layer and stick with it. If you’d rather stay on a frontend, our guides on how to configure UFW on Linux (which itself sits on top of nftables in modern Ubuntu) cover that side cleanly.
Once nothing else is fighting you for control, enable and start the service:
sudo systemctl enable --now nftables
sudo nft list ruleset
That second command dumps your entire active ruleset. On a fresh install it’ll probably be empty or near-empty. Ubuntu’s own Ubuntu nftables security documentation is worth bookmarking for distro-specific quirks.
Essential nft Commands to Know
Before you build a real firewall, you need a working vocabulary. These are the nft commands I use every single week.
Listing and Inspecting Rules
# Dump everything
sudo nft list ruleset
# Show only tables
sudo nft list tables
# List a specific table
sudo nft list table inet filter
# Include rule handles (you need these to delete rules)
sudo nft -a list ruleset
Adding Tables and Chains
# Create an inet table named "filter"
sudo nft add table inet filter
# Create a base input chain with default-drop policy
sudo nft add chain inet filter input \
'{ type filter hook input priority 0; policy drop; }'
Adding, Inserting, and Deleting Rules
# Allow established and related connections
sudo nft add rule inet filter input ct state established,related accept
# Allow SSH
sudo nft add rule inet filter input tcp dport 22 accept
# Delete rule by handle number
sudo nft delete rule inet filter input handle 7
# Flush everything (use with extreme caution)
sudo nft flush ruleset
Pro tip: before you write rules for a service, confirm what’s actually listening. Our walkthrough on the ss command and the broader check listening ports in Linux guide will save you from writing rules for ports that aren’t even open.
Build a Complete Server Firewall from Scratch
Lockout warning
Always allow SSH before applying a default-drop policy. I have personally locked myself out of a remote VPS at 2 AM by getting this order wrong, and I had to file a console-access ticket to claw it back. Don’t be me.
Let’s put it all together. Here’s a complete /etc/nftables.conf for a typical web server. It uses the inet family so the same rules cover IPv4 and IPv6.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback
iif lo accept
# Allow established/related (do this BEFORE port rules — efficiency)
ct state established,related accept
# Drop invalid packets
ct state invalid drop
# SSH
tcp dport 22 accept
# HTTP / HTTPS
tcp dport { 80, 443 } accept
# ICMP (ping) — both v4 and v6
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Walk through the logic with me. We flush the ruleset first so this file is the single source of truth. The input chain defaults to drop, then allows loopback (lots of services talk to themselves over lo), then accepts established connections (most traffic on a live server matches here, so putting it first is a performance win). Then we drop invalid packets, accept SSH, HTTP, HTTPS, and ICMP.
The official official nftables server ruleset reference on the upstream wiki is worth cross-checking if you want the canonical example.
Speaking of SSH — opening port 22 is just step one. You still want to harden the daemon itself. Pair this firewall with our fail2ban brute force protection setup, a hardened SSH config file, and make sure you’re authenticating with generate SSH keys instead of passwords. nftables limits who can knock on port 22; SSH keys decide who actually gets in. And if you use SSH tunneling, remember that tunnels ride on the same port 22 rule.
Got nginx on the box? Our walkthrough on how to set up nginx on Linux pairs neatly with the ports 80/443 rules above.
Making Your nftables Rules Persistent
Here’s the trap that catches everyone exactly once. Rules added with nft add rule live in kernel memory only. They vanish at reboot. I made this mistake on a customer’s staging box years ago. Spent an hour crafting a perfect ruleset, rebooted to test a kernel update, and watched the whole firewall evaporate.
To persist your rules:
- Save the current ruleset:
sudo nft list ruleset > /etc/nftables.conf - Validate the syntax before applying:
sudo nft -c -f /etc/nftables.conf(the-cflag means “check only, don’t apply”) - Apply without reboot:
sudo nft -f /etc/nftables.conf - Enable on boot:
sudo systemctl enable nftables
Always put flush ruleset as the first line of /etc/nftables.conf. That gives you atomic full-replacement — old rules gone, new rules in place, in one kernel operation, no gaps. This is the trick that makes deploys safe.
Power Features: Sets, Maps, and Migrating from iptables
Using Sets to Block or Allow Multiple IPs
Sets are where nftables genuinely outclasses iptables. Imagine you have a blocklist of 10,000 IPs. With iptables, every packet walked the rule list linearly until it matched. With nftables, you stuff those IPs into a set and the kernel hashes them for O(1) lookups. It’s not a small difference at scale.
# Create a named set
sudo nft add set inet filter blocklist '{ type ipv4_addr; flags interval; }'
# Add some IPs
sudo nft add element inet filter blocklist '{ 198.51.100.5, 203.0.113.0/24 }'
# Reference the set in a rule
sudo nft add rule inet filter input ip saddr @blocklist drop
Migrating from iptables with iptables-translate
If you have an existing iptables ruleset and want to move over, nftables ships translation tools:
# Translate a single rule
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# Translate an entire saved iptables ruleset
iptables-save | iptables-restore-translate -f -
The output isn’t always idiomatic — you’ll want to consolidate into inet tables and use sets — but it’s a great starting point.
Power-user bonus: nftables pairs beautifully with sysctl kernel tuning for things like net.ipv4.ip_forward when you’re building NAT or routing setups. And if you ever need to verify which traffic is actually hitting which rule, our tcpdump packet analysis guide is the right next step.
Common nftables Mistakes (And How to Avoid Them)
I’ve stepped on every one of these landmines so you don’t have to.
- Ephemeral rules disappear at reboot. Always save to
/etc/nftables.confand enable the systemd service. - Default-drop before allowing SSH. The classic lockout. Allow SSH first, every time, no exceptions.
- Running firewalld AND direct nftables rules. You will get unexpected conflicts. Pick one. If you want to stay with the frontend approach, our firewalld guide covers it properly.
- Skipping syntax validation. Always run
sudo nft -c -f /etc/nftables.confbefore applying a new config file. - Assuming iptables ordering still applies. nftables uses hooks and priorities, not the linear table ordering iptables used. Read the model, don’t translate by reflex.
To test that your rules actually work, scan your server from another box on the network with our nmap port scanner walkthrough. If a port you expected to be closed is showing as open, your rules aren’t doing what you think. And when firewall changes cause weird connectivity problems, our guide on how to troubleshoot network issues in Linux will save you a few hours of head-scratching.
Where to Go From Here
nftables genuinely is a better firewall than iptables once the mental model clicks. Atomic updates, unified IPv4/IPv6, real performance at scale, cleaner syntax. The hardest part of the switch is unlearning iptables muscle memory — which honestly took me a few weekends of homelab pain.
If you’re building out a full security stack, my recommended next reads on this site are the fail2ban brute force protection guide to layer behavioral defense on top of your firewall, the SSH config file deep-dive to harden the daemon itself, and our troubleshoot network issues in Linux reference for when something inevitably misbehaves.
Got a config you’re proud of, a horror story of locking yourself out, or a question I didn’t cover? Hit me up — and if you want more Linux deep-dives like this, browse the Linux Guides archive or subscribe so the next one lands in your inbox.




