LinuxXXV · Firewallsiptables
iptables legacy and migration to nftables
What you'll learn
- Read an iptables ruleset
- Understand why iptables is deprecated
- Migrate an iptables ruleset to nftables
- Use iptables-nft as a compatibility layer
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09
iptables is the legacy Linux firewall tool. It is deprecated in favour of nftables but still appears in older documentation and existing rulesets. This lesson covers iptables, the migration path, and the iptables-nft compatibility layer.
Why iptables is deprecated
The Linux kernel team has merged nftables as the unified firewall API. iptables now runs as a compatibility shim over nftables. Issues with iptables:
- Separate binaries for IPv4 (iptables), IPv6 (ip6tables), ARP (arptables), bridge (ebtables).
- Verbose syntax with separate commands for every option.
- No native transactional updates - rules apply one at a time.
- Limited counters and no native sets.
nftables fixes all of these with a unified syntax, atomic updates, and better performance.
The iptables tables and chains
sudo iptables -L -n -v # list filter table
sudo iptables -t nat -L -n -v # list NAT table
sudo iptables -t mangle -L -n -v # list mangle table
sudo iptables -t raw -L -n -v # list raw table
Tables: filter (default), nat, mangle, raw,
security. Chains: PREROUTING, INPUT, FORWARD,
OUTPUT, POSTROUTING. Each chain has a default policy
(ACCEPT or DROP).
A minimal iptables ruleset
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow established
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH from management
iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 22 -j ACCEPT
# Allow ICMP from monitoring
iptables -A INPUT -p icmp -s 10.0.0.0/24 -j ACCEPT
# Drop invalid
iptables -A INPUT -m state --state INVALID -j DROP
The -m flag loads a module (state, conntrack, multiport,
etc.). The -j flag is the jump target (ACCEPT, DROP,
REJECT, LOG, or a user-defined chain).
Migration to nftables
Step 1: install nftables and iptables-nft (often already installed).
Step 2: dump the iptables ruleset in a format nft can understand:
iptables-save > /tmp/iptables.rules
Step 3: translate the saved ruleset with
iptables-restore-translate:
# Note the tool name: iptables-RESTORE-translate takes a file.
iptables-restore-translate -f /tmp/iptables.rules > /tmp/translated.nft
# Make the file idempotent, then check and load it.
sed -i '1i flush ruleset' /tmp/translated.nft
nft -c -f /tmp/translated.nft # check syntax, change nothing
nft -f /tmp/translated.nft # apply atomically
Step 4: validate the new ruleset behaves the same way. Translation is mechanical; equivalence is not. Compare the rulesets you actually intend to compare, and then test behaviour from outside the host:
# Before the change, on the still-legacy host:
nft list ruleset > /tmp/ruleset.before
sudo nmap -Pn -p- firewall-host > /tmp/scan.before # from a peer host
# After loading /tmp/translated.nft:
nft list ruleset > /tmp/ruleset.after
diff -u /tmp/ruleset.before /tmp/ruleset.after
sudo nmap -Pn -p- firewall-host > /tmp/scan.after
diff -u /tmp/scan.before /tmp/scan.after # must be empty
The external scan is the part that matters. It is the only check that tests the reachability your users depend on rather than the text of a config file.
iptables-nft compatibility layer
Most modern distributions ship iptables-nft, which routes
iptables commands through the nftables backend:
ls -l /usr/sbin/iptables
update-alternatives --display iptables
On RHEL, the alternatives are iptables-legacy and
iptables-nft. On Debian, similar.
If you have a service that hard-codes iptables commands and you want to use nftables underneath:
sudo update-alternatives --set iptables /usr/sbin/iptables-nft
iptables commands now create nftables rules transparently.
Read iptables output
iptables -L -n -v --line-numbers
Output:
num pkts bytes target prot opt in out source destination
1 1234 100K ACCEPT all -- lo any 0.0.0.0/0 0.0.0.0/0
2 987 65.2K ACCEPT all -- any any 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 0 0 ACCEPT tcp -- any any 10.0.0.0/24 0.0.0.0/0 tcp dpt:22
4 42 3.5K ACCEPT icmp -- any any 10.0.0.0/24 0.0.0.0/0
The line numbers are essential for inserting or deleting specific rules.
Persist iptables rules
# Debian/Ubuntu
sudo apt install iptables-persistent
sudo netfilter-persistent save
# RHEL family
sudo yum install iptables-services
sudo service iptables save
This saves the current rules to /etc/iptables/rules.v4
(Debian) or /etc/sysconfig/iptables (RHEL).
Knowledge check
Knowledge check · 5 questions
Q1. Why is iptables deprecated in favour of nftables?
Q2. iptables-nft routes iptables commands through the nftables backend.
Q3. Which of the following are iptables tables? Select all that apply.
Q4. You have /tmp/iptables.rules from iptables-save and want the whole ruleset in nft syntax. Which command do you run?
Q5. Once nft -c -f accepts the translated file, the migration is verified.
Passing score: 75%. Answers are checked in this browser.