Skip to main content
Back to Category

iptables vs nftables: Comparison and Migration Guide

Comprehensive comparison of iptables and nftables, nftables syntax, migration guide, common rule equivalents, and when to use which firewall tool.

Read time: 13 min Security
iptablesnftablesfirewalllinuxnetwork securitypacket filteringnetfilterfirewall rules

Table of Contents

iptables vs nftables: Comparison and Migration Guide

For many years, iptables was the go-to tool for packet filtering on Linux. However, nftables has been included in the Linux kernel since 2014 and is replacing iptables in modern distributions. This guide compares the two tools, teaches nftables syntax, and walks you through migrating from iptables to nftables.

Comparison Table

Featureiptablesnftables
First release19982014
SyntaxComplex, inconsistentConsistent, readable
IPv4/IPv6Separate tools (iptables/ip6tables)Single tool
PerformancePer-rule evaluationOptimized
Atomic updatesNoYes
Rule setsSeparate tablesUnified
Default (Ubuntu 20.04+)NoYes
Default (Debian 10+)NoYes

iptables Basic Concepts

hljs bash
# View current iptables rules
sudo iptables -L -n -v
sudo iptables -L -n -v --line-numbers

# Tables: filter, nat, mangle, raw
sudo iptables -t nat -L -n -v

# Chains: INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING

# Basic rules
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -P INPUT DROP

# Save rules
sudo iptables-save > /etc/iptables/rules.v4
sudo ip6tables-save > /etc/iptables/rules.v6

nftables Basic Concepts

In nftables, the structure is: table → chain → rule

hljs bash
# Install nftables
sudo apt install nftables -y
sudo systemctl enable nftables
sudo systemctl start nftables

# View current rules
sudo nft list ruleset

# List all tables
sudo nft list tables

# View specific table
sudo nft list table inet filter

nftables Configuration File

hljs bash
sudo nano /etc/nftables.conf
#!/usr/sbin/nft -f

# Clear existing rules
flush ruleset

# inet family covers both IPv4 and IPv6
table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        
        # Allow loopback interface
        iif lo accept
        
        # Allow established connections
        ct state established,related accept
        
        # ICMP (ping)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept
        
        # SSH
        tcp dport 22 accept
        
        # HTTP/HTTPS
        tcp dport { 80, 443 } accept
        
        # Log and drop
        log prefix "nftables-drop: " drop
    }
    
    chain forward {
        type filter hook forward priority 0; policy drop;
    }
    
    chain output {
        type filter hook output priority 0; policy accept;
    }
}
hljs bash
# Apply configuration
sudo nft -f /etc/nftables.conf

# Check syntax (without applying)
sudo nft -c -f /etc/nftables.conf

Rule Equivalents

Basic Rules

iptablesnftables
iptables -A INPUT -p tcp --dport 22 -j ACCEPTnft add rule inet filter input tcp dport 22 accept
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPTnft add rule inet filter input ip saddr 192.168.1.0/24 accept
iptables -A INPUT -j DROPnft add rule inet filter input drop
iptables -P INPUT DROPtype filter hook input priority 0; policy drop;

NAT Rules

hljs bash
# iptables NAT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80
# nftables NAT equivalent
table ip nat {
    chain prerouting {
        type nat hook prerouting priority -100;
        
        # Port forwarding (DNAT)
        tcp dport 80 dnat to 192.168.1.10:80
        tcp dport 443 dnat to 192.168.1.10:443
    }
    
    chain postrouting {
        type nat hook postrouting priority 100;
        
        # Masquerade (NAT)
        oif eth0 masquerade
    }
}

Rate Limiting

hljs bash
# iptables rate limiting
sudo iptables -A INPUT -p tcp --dport 22 -m limit --limit 3/min --limit-burst 5 -j ACCEPT
# nftables rate limiting
chain input {
    # SSH rate limiting
    tcp dport 22 limit rate 3/minute burst 5 packets accept
    tcp dport 22 drop
    
    # HTTP rate limiting
    tcp dport 80 limit rate 100/second burst 200 packets accept
}

IP Sets

hljs bash
# iptables ipset
sudo apt install ipset -y
sudo ipset create blocked_ips hash:ip
sudo ipset add blocked_ips 1.2.3.4
sudo iptables -A INPUT -m set --match-set blocked_ips src -j DROP
# nftables sets (built-in)
table inet filter {
    # Define IP set
    set blocked_ips {
        type ipv4_addr
        elements = { 1.2.3.4, 5.6.7.8, 10.0.0.0/8 }
    }
    
    chain input {
        type filter hook input priority 0; policy drop;
        
        # Drop blocked IPs
        ip saddr @blocked_ips drop
        
        # Other rules...
        tcp dport 22 accept
    }
}

Migrating from iptables to nftables

Automatic Conversion

hljs bash
# Install conversion tool
sudo apt install iptables-nftables-compat -y

# Convert existing iptables rules to nftables format
iptables-save | iptables-restore-translate -f /etc/nftables.conf

# Also convert ip6tables rules
ip6tables-save | ip6tables-restore-translate >> /etc/nftables.conf

# Review generated file
cat /etc/nftables.conf

Manual Migration Steps

hljs bash
# 1. Backup existing iptables rules
sudo iptables-save > /root/iptables-backup.txt
sudo ip6tables-save > /root/ip6tables-backup.txt

# 2. Create nftables configuration
sudo nano /etc/nftables.conf

# 3. Test configuration
sudo nft -c -f /etc/nftables.conf

# 4. Enable nftables
sudo systemctl enable nftables
sudo nft -f /etc/nftables.conf

# 5. Disable iptables
sudo systemctl disable iptables
sudo systemctl stop iptables

# 6. Verify rules
sudo nft list ruleset

When to Use Which?

Use iptables:

  • Legacy systems (CentOS 7, Ubuntu 18.04)
  • Existing iptables scripts in place
  • Team is familiar with iptables
  • Third-party tools require iptables

Use nftables:

  • New installations (Ubuntu 20.04+, Debian 10+)
  • Want to manage IPv4 and IPv6 together
  • Want cleaner syntax
  • Need atomic rule updates

Since Ubuntu 20.04 and Debian 10, the iptables command actually runs the iptables-nft wrapper — meaning it uses nftables under the hood. Use iptables-legacy for real iptables.

Conclusion

nftables is replacing iptables in modern Linux systems. It offers more consistent syntax, unified IPv4/IPv6 management, and better performance. Choose nftables for new installations; plan a migration for existing iptables infrastructure.