iptables and nftables Basics - Introduction to Packet Filtering
What Is the Difference Between iptables and nftables?
iptables has been the de facto Linux firewall tool for decades, but nftables is now the modern replacement. Ubuntu 22.04 and later use nftables by default (via an iptables-nft compatibility layer). The rule of thumb is: use iptables for maintaining existing servers, and nftables for new setups.
| Attribute | iptables | nftables |
|---|---|---|
| Introduced | 1998 | 2014 (Linux 3.13) |
| Syntax | Complex, verbose | Unified, concise |
| IPv4/IPv6 | Separate (ip6tables) | Unified (inet family) |
| Ubuntu 22.04 | Via iptables-nft layer | Native |
On Ubuntu 22.04+, running iptables actually routes through nftables internally. Run update-alternatives --list iptables to see which implementation is active.
iptables Structure
iptables organizes rules in a three-level hierarchy: table → chain → rule. Most firewall work happens in the filter table across three chains.
The three chains in the filter table:
- INPUT: Packets destined for this machine
- OUTPUT: Packets originating from this machine
- FORWARD: Packets being routed through (router setups only)
Rule targets:
- ACCEPT: Allow the packet through
- DROP: Silently discard (no notification to sender)
- REJECT: Discard and send an error back
Basic iptables Commands
Always start by reviewing existing rules. Use -n to skip DNS lookups and -v for packet counters.
Viewing Rules
# List all chains with details iptables -L -n -v # List INPUT chain with line numbers iptables -L INPUT -n -v --line-numbers
Adding Rules
# Allow loopback (required) iptables -A INPUT -i lo -j ACCEPT # Allow established connections (required) iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow SSH (port 22) iptables -A INPUT -p tcp --dport 22 -j ACCEPT # Allow HTTP and HTTPS iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT # Drop everything else iptables -A INPUT -j DROP
Deleting and Resetting Rules
# Delete by line number (get numbers with --line-numbers) iptables -D INPUT 3 # Delete by rule specification (replace -A with -D) iptables -D INPUT -p tcp --dport 80 -j ACCEPT # Flush all rules in all chains iptables -F # Reset default policies to ACCEPT iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT
If you flush rules (iptables -F) while the default policy is DROP, any open SSH session will be cut. Always verify the default policy before flushing rules on a remote server.
nftables Structure
nftables uses a four-level hierarchy: family → table → chain → rule. Unlike iptables, you must explicitly create tables and chains before adding rules. Using the inet family lets you handle both IPv4 and IPv6 in a single ruleset.
# Show the entire active ruleset nft list ruleset # Show all tables nft list tables # Show a specific table nft list table inet filter
Basic nftables Commands
Create a table and chain first, then add rules. The type filter hook input priority 0 declaration is the standard pattern for an input filter chain.
Creating Tables and Chains
# Create a table
nft add table inet filter
# Create INPUT chain with drop policy
nft add chain inet filter input '{ type filter hook input priority 0 ; policy drop ; }'
# Create OUTPUT chain with accept policy
nft add chain inet filter output '{ type filter hook output priority 0 ; policy accept ; }'Adding Rules
# Allow loopback
nft add rule inet filter input iif lo accept
# Allow established connections
nft add rule inet filter input ct state established,related accept
# Allow SSH
nft add rule inet filter input tcp dport 22 accept
# Allow HTTP and HTTPS (multiple ports in one rule)
nft add rule inet filter input tcp dport '{ 80, 443 }' acceptDeleting Rules
# List rules with handle numbers nft list ruleset -a # Delete a rule by handle number nft delete rule inet filter input handle 5
Resetting All Rules
# Flush the entire ruleset nft flush ruleset # Or delete a specific table nft delete table inet filter
nft flush ruleset removes all rules instantly. If any chain has a policy drop, all traffic will be blocked. Verify the policy before running this on a remote server.
Persisting Rules Across Reboots
Both iptables and nftables rules are lost on reboot by default. Persistence requires saving the configuration.
Persisting iptables (Ubuntu)
# Install iptables-persistent apt install iptables-persistent # Save current rules netfilter-persistent save # Or save manually iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6
Persisting nftables (Ubuntu)
# Enable nftables service systemctl enable nftables # Save current ruleset to config file nft list ruleset > /etc/nftables.conf # Restart service to verify systemctl restart nftables systemctl status nftables
Basic /etc/nftables.conf template:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state established,related accept
tcp dport 22 accept
tcp dport { 80, 443 } accept
}
chain output {
type filter hook output priority 0; policy accept;
}
}On Ubuntu 22.04, the nftables.service is included by default. Edit /etc/nftables.conf and run systemctl restart nftables to apply changes.
Relationship with firewalld and ufw
On RHEL / CentOS / Fedora, firewalld acts as a frontend to nftables. On Ubuntu, ufw (Uncomplicated Firewall) provides a simpler interface to nftables/iptables and is recommended for everyday use.
# ufw basics (Ubuntu) ufw status verbose ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable ufw status numbered
For day-to-day firewall management on Ubuntu, ufw is the simplest option. Use iptables or nftables directly when you need fine-grained control or are building complex filtering rules.