BlogLinux & scripting

From iptables to nftables: a practical migration

Translate your ruleset to nftables' cleaner syntax and sets, and run both during the cutover without lockouts.

May 20, 2025·4 min readAdvanced·By the SecOpsLog team · command-tested

For years, iptables was the Linux firewall userspace front end most admins knew. Modern kernels prefer nftables — one nft binary, consistent syntax, native sets and maps, and no translation layer between ipv4 and ipv6 rules. Distros ship iptables-nft shims so old scripts keep working, but new rules should be written in nftables native syntax so you are not debugging double indirection at 2am.

Cloud security groups remain the primary edge control for VMs — host nftables is defense in depth when an SG is misconfigured or for bare-metal without a hypervisor envelope. Treat host firewall as compensating control, not the only gate.

This note translates a classic iptables ruleset to nftables, runs both during cutover on a test host, and shows persistence with nft list ruleset > /etc/nftables.conf. For host hardening context see Linux hardening; for detecting blocked scans and firewall changes, Linux detection engineering.

iptables to nftables migration

Work on a host with console access. Flush test rules before applying default-drop. Keep ssh allow rule first in every iteration.

1Export iptablesiptables-save > backup.rules2Install nftablesdisable legacy if needed3Translate rulessets for allowlists4nft -c -f rulesetcheck syntax offline5Apply with sshallowinput chain first rule6Test from secondsessioncurl + ssh7Enablenftables.servicepersist at boot

Translate a simple allowlist

iptables -m set --match-set becomes an nftables set with automatic element updates. Inline ip lists in iptables explode into unmaintainable one-liners; nftables set blocks are readable and fast.

Use meta nftrace set 1 or nflog groups sparingly for dropped-packet debugging — send copies to userspace loggers without printf-in-chain hacks. Document chain priorities (priority filter - 10) when Docker or Kubernetes inserts their own tables so your drop policy still runs where you expect.

/etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
set admin_ips {
type ipv4_addr
elements = { 203.0.113.10, 203.0.113.11 }
}
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 ip saddr @admin_ips accept
tcp dport { 80, 443 } accept
}
}

Old iptables equivalent

The iptables version used separate iptables and ip6tables invocations, -A INPUT append order mattered, and ipsets required a second tool. nftables inet table handles both address families in one file.

During migration, iptables-nft-save can dump translated rules for comparison. Run both stacks in audit mode if your distro supports it — log what legacy would drop vs what nft drops — before decommissioning iptables-legacy services.

iptables-legacy.sh
# Fragile — order-dependent, ipv4-only
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -P INPUT DROP
bash — apply and verify nftableslive
nft -c -f /etc/nftables.conf
syntax check passed
nft -f /etc/nftables.conf
nft list ruleset | head -20
ss -tlnp | grep :22
ssh still listening — test login before closing session
Default DROP without an SSH allow locks you out
Always insert admin source allow (or conntrack established) before setting policy drop. Apply from IPMI/serial if remote. Docker and kube-proxy inject their own rules — audit `nft list ruleset` after container runtime starts or you may wonder why traffic still flows.
nftables vs iptables-legacy
Prefer native nft
New rulesets from scratch
Sets/maps for allowlists
Single inet table v4+v6
Readable chain priorities
Keep shim temporarily
Legacy automation unmigrated
Vendor scripts expect iptables
Gradual per-chain migration
Document until decommissioned

Where this goes next

Host firewall is one layer — pair with cloud security groups, SSH hardening, and centralized logging of dropped packets via nflog or audit. Linux hardening covers SSH and systemd; Linux detection engineering shows how to alert on nft rule changes and port scan patterns in logs.

Outbound filtering matters for compromised workloads — a chain output policy drop with exceptions for DNS and NTP limits C2 exfiltration. Document emergency break-glass rules that allow your admin IP before any mass rollout.

Go deeper in a courseLinux hardeningFirewall, SSH, audit, and layered defense for Linux servers.View course

Related posts