For decades, Linux administrators relied on the legacy iptables, ip6tables, and arptables utilities for packet inspection and network address translation. However, these tools suffered from separate codebases, inefficient linear rule evaluation, and complex syntax. nftables replaced the legacy Netfilter subsystem, uniting IPv4, IPv6, ARP, and bridging into a single kernel-level virtual machine. By leveraging sets, maps, and atomic transactions, nftables delivers significantly higher throughput and unified firewall administration.
Understanding the nftables Architecture: Tables, Chains, and Rules
Unlike iptables, which enforced predefined tables (filter, nat, mangle) with hardcoded chains, nftables uses an entirely customizable hierarchy:
- Address Families: Defines the network protocol domain:
ip(IPv4),ip6(IPv6),inet(dual-stack IPv4/IPv6 unified),arp, andbridge. - Tables: Arbitrary containers created by the administrator to house specific chains and rules.
- Chains: Hook points where packets are intercepted:
- prerouting: Evaluates packets immediately upon arrival before routing decisions.
- input: Filters packets destined for the local host.
- forward: Filters packets being routed through the host to other interfaces.
- output: Filters packets originated by local processes.
- postrouting: Handles outbound modifications (such as SNAT/masquerade) prior to transmission.
- Rules: Conditional expressions evaluated inside chains that trigger verdicts (
accept,drop,reject,log, orjump).
Installing and Checking nftables Service Status
Most modern Linux distributions include nftables in the base installation. Ensure the management packages are installed:
sudo apt update
sudo apt install nftables -y
Enable and start the systemd service to persist firewall rules across reboots:
sudo systemctl enable --now nftables
Inspect the currently active ruleset:
sudo nft list ruleset
If no rules are configured, the command returns empty, indicating a clean slate.
Building a Dual-Stack Stateful Firewall Ruleset
Using the inet family, you can establish baseline protection for both IPv4 and IPv6 within a single configuration block.
Create a dedicated table named filter:
sudo nft add table inet filter
Add a standard input chain hooked to the Netfilter input stage with a default drop policy:
sudo nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }'
Add stateful inspection rules to permit loopback traffic and established connections:
# Permit traffic on the local loopback interface
sudo nft add rule inet filter input iifname "lo" accept
# Permit established and related connection states
sudo nft add rule inet filter input ct state established,related accept
# Drop invalid packets immediately
sudo nft add rule inet filter input ct state invalid drop
Open required public services (such as SSH on port 22 and HTTPS on port 443) using anonymous sets:
sudo nft add rule inet filter input tcp dport { 22, 80, 443 } ct state new accept
Allow essential ICMP diagnostics (ping and IPv6 neighbor discovery):
sudo nft add rule inet filter input ip protocol icmp icmp type { echo-request, echo-reply } accept
sudo nft add rule inet filter input ip6 nexthdr icmpv6 accept
Configuring Forward and Output Chains
To regulate forwarded and outbound host traffic:
# Create forward chain (block forwarding by default on non-router hosts)
sudo nft 'add chain inet filter forward { type filter hook forward priority 0; policy drop; }'
# Create output chain (allow all outbound client lookups and sessions)
sudo nft 'add chain inet filter output { type filter hook output priority 0; policy accept; }'
Saving and Atomically Applying Configuration Files
To persist your firewall ruleset across server reboots, export the live configuration to /etc/nftables.conf:
sudo sh -c 'nft list ruleset > /etc/nftables.conf'
When updating rules in production, test syntax without applying changes using the -c check flag:
sudo nft -c -f /etc/nftables.conf
To apply complex updates atomically (guaranteeing that either all rules load or none do, preventing accidental remote lockouts):
sudo nft -f /etc/nftables.conf