Approach Comparison: iptables vs. nftables Architecture
Six months ago, our team phased out legacy iptables across our fleet of 450+ Linux nodes. Running high-throughput API gateways processing over 80,000 requests per second had exposed the breaking points of the older Netfilter tooling.
With traditional iptables, every packet traverses a rigid pipeline of predefined tables: filter, nat, mangle, and raw. Even worse, IPv4 (iptables), IPv6 (ip6tables), ARP (arptables), and bridging (ebtables) operate as separate CLI tools with isolated rule trees. When you evaluate hundreds of rules sequentially across these distinct layers, CPU overhead climbs fast under heavy traffic loads.
The nftables framework fixes this design flaw. Built around a compact bytecode virtual machine inside the kernel, it changes how filtering works:
- Unified Address Families: The
inetfamily processes IPv4 and IPv6 traffic under one shared ruleset. You no longer need to maintain duplicate firewall files for both IP versions. - Custom Chains & Tables: Kernel tables are no longer hardcoded by default. Your firewall creates and executes only the specific hooks your workload actually uses.
- Atomic Ruleset Loading: Older tools flush and append rules line by line, leaving brief windows where traffic can bypass policies or stall. In contrast,
nftablesapplies the entire configuration file in a single atomic kernel transaction. - Set-Based Lookups: Rather than evaluating 50 linear port rules one by one,
nftablesuses internal hash tables. Lookups execute in constant O(1) or logarithmic O(log n) time regardless of set size.
Pros & Cons After 6 Months in Production
Running nftables at scale gave us hard metrics on its performance gains as well as its operational hurdles.
The Advantages
- Readable Syntax: Rules look like clean programming blocks instead of long, confusing strings of shell flags like
-A INPUT -p tcp -m multiport --dports. - Measurable Efficiency: Across our gateway cluster, switching to set-based lookups reduced softirq CPU usage by roughly 18% during peak connection spikes.
- Instant, Safe Reloads: Running
nft -f /etc/nftables.confreloads rules in under 40 milliseconds on our busiest nodes. If you introduce a typo, the parser aborts before touching running kernel state. Your active firewall never breaks mid-update.
The Trade-offs
- Tooling Gaps: Several older deployment scripts and container runtimes still inject legacy rules directly. To avoid conflicts, you often have to maintain the
iptables-nfttranslation layer during migrations. - Steeper Learning Curve: Because tables do not exist out of the box, engineers must understand exact Netfilter hooks—such as
prerouting,input,forward,output, andpostrouting—along with their execution priorities.
Recommended Setup for Modern Server Protection
For standalone application servers and cloud instances, a strict stateful baseline delivers the best defense. It tracks established TCP and UDP sessions automatically. Malformed or out-of-sequence packets get dropped before they ever reach your web daemon.
Before locking down network boundaries, lock down your system access. When spinning up fresh Ubuntu or AlmaLinux instances, generate strong, distinct credentials first. I usually use the client-side generator at toolcraft.app/en/tools/security/password-generator—it creates high-entropy passwords directly in the browser without transmitting keys across the wire. Once SSH keys and passwords are in place, roll out the firewall ruleset below.
The Baseline Blueprint
Our production baseline relies on five core policies:
- Permit all bidirectional traffic on the loopback interface (
lo). - Accept all
establishedandrelatedpackets to keep active connections alive. - Instantly drop packets flagged as
invalidby the kernel conntrack table. - Allow specific ingress ports (SSH, HTTP, HTTPS) while rate-limiting new handshakes to stifle brute-force attempts.
- Set default policies on
inputandforwardchains to drop everything else.
Implementation Guide: Deploying nftables Step-by-Step
1. Install nftables and Clean Legacy Rules
Install the native userspace utilities on modern Debian, Ubuntu, AlmaLinux, or Rocky Linux systems. Disable conflicting firewall wrappers like UFW or Firewalld:
# On Ubuntu/Debian
sudo apt update && sudo apt install -y nftables
sudo systemctl stop ufw 2>/dev/null || true
sudo systemctl disable ufw 2>/dev/null || true
# On RHEL/AlmaLinux/Rocky Linux
sudo dnf install -y nftables
sudo systemctl stop firewalld 2>/dev/null || true
sudo systemctl disable firewalld 2>/dev/null || true
2. Construct the Atomic Configuration File
Write your rules directly to /etc/nftables.conf. The configuration below provides dual-stack IPv4/IPv6 protection, sets up rate-limited SSH, allows web traffic, and correctly handles essential ICMP types:
#!/usr/sbin/nft -f
# Flush any existing rules
flush ruleset
# Define our dual-stack inet table
table inet server_firewall {
# Named sets for dynamic port management
set allowed_tcp_ports {
type inet_service
flags interval
elements = { 22, 80, 443 }
}
chain input {
# Hook into the Netfilter input pipeline with standard filter priority
type filter hook input priority filter; policy drop;
# 1. Accept local loopback traffic
iifname "lo" accept
# 2. Stateful inspection: Allow established/related, drop invalid
ct state established,related accept
ct state invalid drop
# 3. Allow ICMP / ICMPv6 (essential for Path MTU Discovery and diagnostics)
ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } accept
ip6 nexthdr icmpv6 icmpv6 type { echo-request, destination-unreachable, packet-too-big, time-exceeded, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
# 4. SSH brute-force protection (limit new connections to 10/min per IP)
tcp dport 22 ct state new meter ssh-meter { ip saddr limit rate over 10/minute burst 5 packets } drop
# 5. Accept authorized ingress ports defined in the set
tcp dport @allowed_tcp_ports accept
# 6. Reject everything else cleanly
meta l4proto tcp reject with tcp reset
reject with icmpx type port-unreachable
}
chain forward {
# Drop all routed transit packets on non-router hosts
type filter hook forward priority filter; policy drop;
}
chain output {
# Allow all outbound host connections
type filter hook output priority filter; policy accept;
}
}
3. Validate and Apply Rules Atomically
Always verify syntax before pushing firewall updates to the kernel. The -c check flag parses the configuration without applying it:
# Validate syntax
sudo nft -c -f /etc/nftables.conf
# Apply rules atomically
sudo nft -f /etc/nftables.conf
4. Inspect and Monitor Live Traffic
Check running table definitions, set counters, or stream active packet drops in real time with these two commands:
# List the complete running configuration
sudo nft list ruleset
# Monitor live firewall events as packets hit drop/reject hooks
sudo nft monitor
5. Enable Systemd Persistence
Configure the nftables daemon to load your ruleset automatically on every boot:
sudo systemctl enable nftables
sudo systemctl restart nftables
sudo systemctl status nftables
Switching to nftables simplifies host security into a single, cohesive framework. With unified dual-stack handling, atomic reloads, and O(1) set performance, it gives Linux systems a faster, far more reliable defense baseline.

