funwithlinux guide

Firewalls 101: Transitioning from iptables to nftables

In the realm of Linux networking, firewalls are the first line of defense, controlling traffic flow and securing systems from unauthorized access. For decades, **iptables** has reigned as the de facto firewall tool, leveraging the Linux kernel’s netfilter framework to enforce rules. However, as networks grow in complexity and performance demands rise, iptables has shown its age—cumbersome syntax, limited scalability, and inefficient rule processing. Enter **nftables**, the modern successor to iptables, designed to address these shortcomings with a unified, flexible, and high-performance architecture. This blog will guide you through the transition from iptables to nftables, explaining why the shift matters, key differences, and how to migrate your existing firewall rules seamlessly. Whether you’re a system administrator, DevOps engineer, or hobbyist, this guide will equip you with the knowledge to embrace nftables confidently.

Table of Contents

  1. Understanding iptables: The Legacy Workhorse
  2. Enter nftables: The Modern Firewall
  3. Why Transition from iptables to nftables?
  4. Key Differences Between iptables and nftables
  5. Getting Started with nftables
  6. Migrating from iptables to nftables
  7. Advanced nftables Concepts
  8. Common Pitfalls and How to Avoid Them
  9. Conclusion
  10. References

1. Understanding iptables: The Legacy Workhorse

Before diving into nftables, it’s critical to understand iptables’ role and limitations.

How iptables Works

iptables is a user-space tool that interacts with the Linux kernel’s netfilter framework to manage packet filtering, network address translation (NAT), and port forwarding. It organizes rules into:

  • Tables: Predefined categories of functionality (e.g., filter for packet filtering, nat for NAT, mangle for packet modification).
  • Chains: Sequences of rules within a table (e.g., INPUT for incoming traffic, OUTPUT for outgoing traffic, FORWARD for routed traffic).
  • Rules: Conditions (e.g., source IP, port) and actions (e.g., ACCEPT, DROP, MASQUERADE).

Example iptables Rule

# Allow incoming SSH (port 22) traffic
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Limitations of iptables

  • Fragmented Syntax: Separate commands for tables/chains (e.g., iptables, ip6tables, iptables-nat).
  • Scalability Issues: Rule processing slows with large rule sets (linear traversal).
  • No Built-in Data Structures: Lacks sets/maps for grouping IPs/ports, requiring repetitive rules.
  • Static Rule Management: Updating rules often requires flushing and reloading the entire ruleset, causing downtime.

2. Enter nftables: The Modern Firewall

nftables, introduced in Linux kernel 3.13 (2014), is a complete rewrite of the netfilter user-space tooling. It retains netfilter’s core power but addresses iptables’ flaws with a unified, efficient design.

Design Goals of nftables

  • Unified Syntax: A single nft command replaces iptables, ip6tables, arptables, and ebtables.
  • Flexible Structure: No predefined tables/chains—users define custom tables (with family support: inet, ip, ip6, etc.) and chains.
  • Advanced Data Structures: Native support for sets, maps, and concatenations to simplify complex rules.
  • Performance: Faster rule processing via kernel optimizations (hash tables, reduced overhead).
  • Dynamic Updates: Modify rules without flushing the entire ruleset.

3. Why Transition from iptables to nftables?

The shift to nftables is driven by tangible benefits:

BenefitDescription
Unified ToolingReplace multiple tools (iptables, ip6tables, etc.) with a single nft command.
Better PerformanceRule lookups use hash tables (O(1) complexity) vs. iptables’ linear traversal (O(n)).
Simpler Rule ManagementSets/maps group IPs/ports (e.g., {192.168.1.0/24, 10.0.0.0/8}) to reduce repetitive rules.
Dynamic UpdatesAdd/remove rules without disrupting existing connections (no iptables -F).
Improved LoggingNative log action with configurable prefixes, rates, and severity levels.
Future-Proofingiptables is deprecated in major distributions (e.g., RHEL 9, Ubuntu 22.04 uses nftables by default for iptables backend).

4. Key Differences Between iptables and nftables

To transition effectively, understand these core distinctions:

Syntax

  • iptables: Uses separate commands per table/chain with flags (e.g., -A to append, -p for protocol).
    iptables -t filter -A INPUT -s 192.168.1.100 -j ACCEPT
  • nftables: Uses a declarative syntax with subcommands (e.g., add rule, list ruleset).
    nft add rule inet filter INPUT ip saddr 192.168.1.100 accept

Structure

  • iptables: Predefined tables (filter, nat, etc.) and chains (INPUT, OUTPUT, etc.).
  • nftables: No predefined tables/chains. Users create tables (with address family: ip, ip6, inet for dual-stack) and chains (with hook points like input, output).

Data Structures

  • iptables: No built-in sets; requires repetitive rules for multiple IPs/ports.
  • nftables:
    • Sets: Groups of values (e.g., {192.168.1.100, 192.168.1.101}) for efficient matching.
    • Maps: Key-value pairs (e.g., map port 8080 to 80, 8443 to 443).

Performance

nftables reduces kernel-user space communication and uses hash tables for rule lookups, making it up to 10x faster than iptables with large rule sets (per kernel benchmarks).

5. Getting Started with nftables

Let’s walk through setting up a basic nftables firewall.

Step 1: Install nftables

Most Linux distributions include nftables by default. Install it if missing:

# Debian/Ubuntu
sudo apt update && sudo apt install nftables -y

# RHEL/CentOS/Fedora
sudo dnf install nftables -y

# Start and enable the service
sudo systemctl enable --now nftables

Step 2: Basic nftables Commands

CommandPurpose
nft list rulesetShow all current rules.
nft add table <family> <name>Create a new table (e.g., inet filter for IPv4/IPv6).
nft add chain <table> <name> { type <type> hook <hook> priority <prio> \; }Create a chain (e.g., input hook for incoming traffic).
nft add rule <table> <chain> <match> <action>Add a rule to a chain.
nft save rulesetSave rules to /etc/nftables.conf.
nft flush rulesetDelete all rules (use with caution!).

Step 3: Build a Basic Ruleset

Let’s create a firewall allowing SSH, HTTP, and HTTPS, while blocking all other incoming traffic.

1. Create a Table and Chains

# Create an "inet" table (supports IPv4/IPv6) named "filter"
sudo nft add table inet filter

# Add an INPUT chain (handles incoming traffic)
sudo nft add chain inet filter INPUT { type filter hook input priority 0 \; policy drop \; }

# Add an OUTPUT chain (handles outgoing traffic)
sudo nft add chain inet filter OUTPUT { type filter hook output priority 0 \; policy accept \; }

# Add a FORWARD chain (handles routed traffic)
sudo nft add chain inet filter FORWARD { type filter hook forward priority 0 \; policy drop \; }
  • policy drop: Default action if no rules match (deny all).

2. Add Rules to Allow Essential Traffic

# Allow loopback traffic (lo interface)
sudo nft add rule inet filter INPUT iif lo accept

# Allow established/related connections (e.g., HTTP responses)
sudo nft add rule inet filter INPUT ct state established,related accept

# Allow SSH (port 22)
sudo nft add rule inet filter INPUT tcp dport 22 accept

# Allow HTTP (port 80) and HTTPS (port 443)
sudo nft add rule inet filter INPUT tcp dport {80, 443} accept

3. Save the Ruleset

sudo nft save ruleset  # Saves to /etc/nftables.conf by default

Verify with nft list 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;
  }
  chain FORWARD {
    type filter hook forward priority 0; policy drop;
  }
}

6. Migrating from iptables to nftables

Migrating involves auditing existing rules, translating them to nftables, and validating functionality.

Step 1: Audit Existing iptables Rules

First, export your iptables rules:

sudo iptables-save > iptables-rules.txt  # IPv4
sudo ip6tables-save > ip6tables-rules.txt  # IPv6 (if used)

Step 2: Use iptables-translate for Automated Conversion

The iptables-translate tool (included with iptables-nft) converts iptables rules to nftables syntax.

Example Conversion

# Convert an iptables rule to nftables
sudo iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT

Output:

nft add rule ip filter INPUT tcp dport 22 accept

For bulk conversion, pipe iptables-save to iptables-translate:

sudo iptables-save | iptables-translate > nftables-rules.nft

Step 3: Manual Conversion Examples

Some rules require manual adjustment. Here are common scenarios:

Basic Allow/Deny

iptables Rulenftables Equivalent
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPTnft add rule ip filter INPUT ip saddr 192.168.1.0/24 accept
iptables -A INPUT -p udp --dport 53 -j DROPnft add rule ip filter INPUT udp dport 53 drop

NAT (Port Forwarding)

iptables:

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.10:80
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

nftables:

# Create a nat table
nft add table ip nat
nft add chain ip nat PREROUTING { type nat hook prerouting priority 0 \; }
nft add chain ip nat POSTROUTING { type nat hook postrouting priority 100 \; }

# Add DNAT rule
nft add rule ip nat PREROUTING tcp dport 8080 dnat to 10.0.0.10:80

# Add MASQUERADE rule
nft add rule ip nat POSTROUTING oif eth0 masquerade

Step 4: Test and Validate

  • Load the new ruleset: sudo nft -f nftables-rules.nft.
  • Test connectivity: Verify SSH, HTTP, and other critical services work.
  • Monitor logs: Check journalctl -u nftables for errors.

7. Advanced nftables Concepts

nftables’ power lies in advanced features like sets, maps, and concatenations.

Sets: Grouping Values

Sets simplify rules by grouping IPs, ports, or protocols.

Example: Allow Traffic from a List of IPs

# Create a set of trusted IPs
nft add set ip filter trusted_ips { type ipv4_addr \; elements = { 192.168.1.100, 10.0.0.5 } \; }

# Allow traffic from trusted IPs
nft add rule ip filter INPUT ip saddr @trusted_ips accept

Maps: Key-Value Pairs

Maps map keys (e.g., ports) to values (e.g., backend IPs) for dynamic port forwarding.

Example: Port Forwarding with a Map

# Create a map: { external_port : internal_ip:internal_port }
nft add map ip nat port_map { type inet_service : ipv4_addr_port \; elements = { 8080 : 10.0.0.10:80, 8443 : 10.0.0.10:443 } \; }

# Use the map in a DNAT rule
nft add rule ip nat PREROUTING tcp dport map @port_map dnat to ip daddr map @port_map

8. Common Pitfalls and How to Avoid Them

  • Syntax Errors: nftables is strict with spacing (e.g., ip saddr not ip saddr). Use nft -c add rule ... to check syntax.
  • Missing Tables/Chains: Unlike iptables, nftables requires explicit table/chain creation.
  • Overlooking IPv6: Use the inet family to handle IPv4/IPv6 in one table, or separate ip/ip6 tables.
  • Forgetting to Save Rules: nft save ruleset ensures rules persist across reboots.
  • Legacy Dependencies: Some iptables modules (e.g., xt_recent) lack nftables equivalents—use native nftables features instead (e.g., sets).

9. Conclusion

nftables represents a significant leap forward in Linux firewall technology, offering simplicity, performance, and scalability that iptables cannot match. While transitioning requires learning new syntax and concepts, tools like iptables-translate ease the process, and the long-term benefits—faster rule processing, dynamic updates, and future-proofing—make it worthwhile.

By following this guide, you’ll be well-equipped to migrate your firewall rules and harness nftables’ full potential.

10. References