nftables: Modern Linux Firewalling
For nearly two decades, iptables was the standard way to configure the Linux firewall. While it is still widely used, modern Linux distributions are increasingly adopting nftables as the preferred packet filtering framework.
Unlike iptables, which evolved over many years through multiple utilities and extensions, nftables was designed as a clean replacement with a simpler architecture, better performance, and greater flexibility.
If you're starting with a modern Linux distribution such as Debian 12, Ubuntu 24.04, Fedora, or RHEL 9, there is a good chance that your firewall is already powered by nftables, even if you still use the iptables command.
In this chapter, you'll learn how nftables is organized, how to write firewall rules, and how to build practical firewalls using its native syntax.
Why nftables?
As Linux networking evolved, the limitations of iptables became increasingly apparent.
Some of its challenges included:
- separate tools for IPv4 and IPv6,
- duplicated rule sets,
- multiple independent utilities (
iptables,ip6tables,ebtables,arptables), - inefficient rule evaluation in large firewalls,
- inconsistent syntax between features.
To address these issues, the Linux kernel introduced nftables.
The goals were:
- one framework for all protocol families,
- simpler syntax,
- more flexible rule matching,
- better performance,
- easier maintenance.
Today, nftables is considered the future of Linux firewalling.
nftables Architecture
Like iptables, nftables configures the netfilter framework.
However, its internal organization is more flexible.
Instead of predefined tables and chains, you create them yourself.
The hierarchy is:
Tables
└── Chains
└── Rules
Unlike iptables, chains are explicitly connected to netfilter hooks when they are created.
Tables
A table groups related chains.
Create a table:
sudo nft add table inet firewall
List tables:
sudo nft list tables
Example:
table inet firewall
Notice the protocol family:
ipip6inetarpbridgenetdev
The inet family is especially useful because one rule set can filter both IPv4 and IPv6 traffic.
Chains
Unlike iptables, chains are not predefined.
You create them and specify:
- which hook they attach to,
- their priority,
- and their default policy.
Example:
sudo nft add chain inet firewall input \
'{ type filter hook input priority 0; policy accept; }'
This creates a chain attached to the INPUT hook.
The important fields are:
- type — filter, nat, route
- hook — input, output, forward, prerouting, postrouting
- priority — execution order relative to other chains
- policy — default action
Rules
Rules are added to chains.
Example:
sudo nft add rule inet firewall input tcp dport 22 accept
Breaking it down:
tcp- destination port
22 - action
accept
The syntax is intentionally close to natural language.
Another example:
sudo nft add rule inet firewall input icmp accept
Listing the Ruleset
Display the complete configuration:
sudo nft list ruleset
Example:
table inet firewall {
chain input {
type filter hook input priority 0;
policy accept;
tcp dport 22 accept
icmp accept
}
}
Unlike iptables, a single command displays the entire ruleset.
Rule Evaluation
Packets are evaluated sequentially.
For example:
tcp dport 22 accept
icmp accept
drop
If an SSH packet arrives:
- rule 1 matches
- evaluation stops
- packet is accepted
If an HTTP packet arrives:
- rule 1 fails
- rule 2 fails
- final rule drops the packet
Just like iptables, rule order matters.
Matches
Rules can match many packet attributes.
Examples include:
Match protocol:
tcp
Match source address:
ip saddr 192.168.1.100
Match destination address:
ip daddr 10.0.0.5
Match source port:
tcp sport 443
Match destination port:
tcp dport 80
Multiple conditions can be combined naturally.
Hands-on Lab: Create Your First Firewall
Warning
Perform these exercises on a virtual machine. Incorrect firewall rules can interrupt remote access.
Step 1
Create a table.
sudo nft add table inet firewall
Step 2
Create an input chain.
sudo nft add chain inet firewall input \
'{ type filter hook input priority 0; policy drop; }'
Notice that the default policy is now drop.
Step 3
Allow loopback traffic.
sudo nft add rule inet firewall input iif lo accept
Many applications rely on loopback communication.
Step 4
Allow established connections.
sudo nft add rule inet firewall input ct state established,related accept
This rule depends on connection tracking, which you learned in the previous chapter.
Without it, replies to existing connections would be blocked.
Step 5
Allow SSH.
sudo nft add rule inet firewall input tcp dport 22 accept
Step 6
Allow ICMP.
sudo nft add rule inet firewall input icmp accept
Display the final configuration:
sudo nft list ruleset
Your ruleset should resemble:
table inet firewall {
chain input {
policy drop;
iif lo accept
ct state established,related accept
tcp dport 22 accept
icmp accept
}
}
You now have a simple stateful firewall.
Sets
One of the most powerful features of nftables is sets.
Instead of writing multiple nearly identical rules:
tcp dport 22 accept
tcp dport 80 accept
tcp dport 443 accept
Create a single rule:
sudo nft add rule inet firewall input tcp dport {22,80,443} accept
This is easier to read and scales much better.
Sets are one of the biggest advantages of nftables over iptables.
Counters
Rules can maintain packet counters.
Example:
sudo nft add rule inet firewall input counter tcp dport 22 accept
Display them:
sudo nft list ruleset
Example:
counter packets 120 bytes 9120
Counters are useful for verifying whether a rule is actually matching traffic.
Logging
To log matching packets:
sudo nft add rule inet firewall input log prefix "INPUT: "
Kernel logs can be viewed using:
journalctl -k
Logging is invaluable when diagnosing firewall behavior.
Deleting Rules
Each rule has a handle number.
Display handles:
sudo nft -a list ruleset
Example:
tcp dport 22 accept # handle 12
Delete it:
sudo nft delete rule inet firewall input handle 12
Flushing Rules
Remove every rule from a table:
sudo nft flush table inet firewall
Delete the table completely:
sudo nft delete table inet firewall
Saving the Configuration
Like iptables, nftables rules exist in kernel memory.
To save them:
sudo nft list ruleset > firewall.nft
Load them again:
sudo nft -f firewall.nft
Most Linux distributions provide a system service that automatically loads a saved configuration during boot. The exact file location and service name vary between distributions.
nftables vs iptables
| Feature | iptables | nftables |
|---|---|---|
| Initial release | 1998 | 2014 |
| IPv4 and IPv6 | Separate tools | Unified (inet) |
| Rule syntax | Older | Cleaner |
| Multiple utilities | Yes | No |
| Sets | Limited | Native support |
| Rule management | Individual commands | Unified ruleset |
| Future development | Maintenance | Active development |
The concepts remain the same because both configure the same netfilter framework.
The difference lies in usability and architecture.
Common Mistakes
Forgetting Loopback
Applications frequently communicate through 127.0.0.1.
Blocking loopback can cause unexpected failures.
Always allow it explicitly.
Omitting Established Connections
Without:
ct state established,related accept
return traffic is often blocked.
This is one of the most common mistakes when creating a firewall from scratch.
Forgetting the Default Policy
If your chain policy is drop, only explicitly allowed traffic will pass.
This is generally a good security practice, but it requires careful testing.
Editing Production Firewalls Blindly
Always keep an alternative management path, such as:
- a virtual machine console,
- out-of-band management,
- or a second SSH session.
This reduces the risk of locking yourself out.
Best Practices
- Prefer the
inetfamily whenever possible. - Build stateful firewalls using connection tracking.
- Use sets instead of repetitive rules.
- Keep rules ordered from most specific to most general.
- Monitor counters during troubleshooting.
- Test firewall changes incrementally.
- Store firewall rules in version control.
A firewall should be predictable, readable, and easy to audit.
Looking Ahead
So far, we have explored how Linux processes packets, how netfilter provides hook points inside the kernel, and how both iptables and nftables configure packet filtering.
The remaining challenge is understanding why packets are accepted or dropped when something goes wrong.
In the next chapter, we will learn how to trace packets through the Linux networking stack, identify where they are being processed, and use debugging tools to troubleshoot complex networking problems.
Summary
nftablesis the modern userspace interface for configuring the Linux netfilter framework.- It replaces the older
iptablesfamily with a unified and more flexible design. - Rules are organized into tables, chains, and rules, but chains are explicitly attached to netfilter hooks.
- The
inetfamily allows a single ruleset to filter both IPv4 and IPv6 traffic. - Stateful firewalls rely on connection tracking through
ct state. - Sets make rule definitions more compact and efficient.
- Rule counters and logging are valuable tools for debugging.
nftablesis the recommended choice for new Linux deployments, while understandingiptablesremains important for maintaining existing systems.