nftables: Migrating From iptables to the Modern Firewall Framework
AI generated
$
/etc
Linux
nftables
Migrating from iptables to the modern firewall framework

iptables has shaped Linux firewalls for two decades, but it hits clear limits with large rule sets and complex logic. nftables replaces iptables, ip6tables, arptables, and ebtables with a single, consistent framework featuring native sets, atomic updates, and noticeably better performance at scale.

11 min read Linux Firewall Networking

1. Why iptables hits its limits with large rule sets

iptables is rule based and evaluates every rule in a chain sequentially from top to bottom. With a few dozen rules that hardly matters, but once a server manages hundreds or thousands of rules, for example for IP based access control or per customer port allowances, evaluation time grows linearly with the number of rules. In the worst case, every packet has to traverse the entire chain before a verdict is reached.

Another structural problem is the lack of atomicity in classic iptables invocations: anyone changing several rules one after another with individual iptables commands risks a short window with an inconsistent rule set, in which packets are either allowed too generously or dropped incorrectly. On top of that, iptables and ip6tables maintain separate rule sets for IPv4 and IPv6, which means double maintenance and encourages inconsistencies between the two protocol versions.

2. The architecture of nftables: tables, chains, and the kernel interpreter

nftables was designed as the successor to iptables, ip6tables, arptables, and ebtables, bundling all four frameworks into one shared kernel infrastructure. Instead of issuing a separate kernel module call for every rule, nftables compiles rule sets into compact bytecode that a virtual machine inside the kernel executes, an approach comparable to the BPF model used by other modern Linux subsystems.

The basic structure consists of tables, which set an address family such as ip, ip6, or the combined inet, chains, which attach to netfilter hooks like input, output, or forward, and rules within those chains. Unlike iptables, the inet address family lets you maintain IPv4 and IPv6 rules together in the same chain, which makes duplicate rule sets unnecessary and structurally enforces consistency between the two protocol versions.


# Create a new table for combined IPv4/IPv6 filtering
nft add table inet filter

# Attach an input chain with default policy drop to the netfilter hook
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

# Show the currently active rule set
nft list ruleset

3. Syntax differences between iptables and nftables in direct comparison

The most noticeable change is the declarative, custom grammar of nftables compared to the many individual flags of iptables. Where iptables requires a separate flag for every condition, such as -p, --dport, or -s, nftables expresses conditions as readable statements that combine protocol, field, and value on a single line, making rules considerably easier for humans to follow.

An SSH rule written in iptables as iptables -A INPUT -p tcp --dport 22 -j ACCEPT reads as nft add rule inet filter input tcp dport 22 accept in nftables. For migrating individual rules, the nftables package ships iptables-translate and ip6tables-translate, which translate an existing iptables command directly into the matching nft syntax, cutting down manual translation effort considerably.


# Translate a single iptables rule into nftables syntax
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT

# Resulting output, usable directly as an nft command
# nft add rule ip filter INPUT tcp dport 22 counter accept

4. Sets and maps: managing large rule volumes efficiently

Sets are one of the biggest structural improvements over iptables. Instead of creating a separate rule for every allowed IP address, a set groups any number of values into a single data structure that the kernel manages internally as a hash table, or, for intervals like IP ranges, as a balanced tree. Checking a set with a thousand entries costs barely more processing time than checking a set with ten entries, whereas the same logic in iptables would mean a thousand individual, sequentially evaluated rules.

Maps go a step further and link a key to a value, for example a destination port number to a verdict action such as accept or drop. That lets you express complex decision tables, which in iptables would have required several separate chains with jump rules, as a single compact nftables map, one that can even be updated at runtime without reloading the entire rule set.


# Create and populate a set of allowed admin IP addresses
nft add set inet filter admin_ips { type ipv4_addr \; flags interval \; }
nft add element inet filter admin_ips { 203.0.113.10, 203.0.113.0/28 }

# Rule referencing the set for SSH access
nft add rule inet filter input tcp dport 22 ip saddr @admin_ips accept

# Map from destination port to verdict for several services at once
nft add map inet filter port_verdict { type inet_service : verdict \; }
nft add element inet filter port_verdict { 80 : accept, 443 : accept, 3306 : drop }
nft add rule inet filter input tcp dport vmap @port_verdict

5. Migration strategy: moving from an existing iptables rule set to nftables

A controlled migration works best in two stages. First, the current rule set is backed up with iptables-save and then fully converted into nftables syntax with iptables-restore-translate, which, unlike single rule translation with iptables-translate, converts the entire rule set including chains and policies in one pass. The resulting nft script should then be reviewed manually to fix up rules that automatic translation does not fully cover, such as certain match modules or complex target actions.

In practice, a parallel run works well: the translated nft rule set is first loaded on a test system or in a separate network namespace and validated against real test cases, before it replaces the existing iptables rule set on production servers. It matters that all rules are loaded from a single file with nft -f before the production cutover, since that lets nftables activate the whole rule set atomically, instead of rule by rule with potential intermediate states as in iptables.


# Back up the existing iptables rule set
iptables-save > /root/iptables-backup.rules

# Translate the full rule set into nftables syntax
iptables-restore-translate -f /root/iptables-backup.rules -o /root/nftables-migrated.nft

# Load and inspect the translated rule set atomically
nft -f /root/nftables-migrated.nft
nft list ruleset

6. The iptables-nft compatibility layer for gradual transitions

For environments where existing automation, configuration management, or monitoring scripts are firmly built around the iptables command, the iptables-nft compatibility layer offers a gentle transition. These are alternative iptables, ip6tables, ebtables, and arptables binaries that accept the same familiar command line syntax, but implement their rules internally through the nftables kernel infrastructure instead of the classic x_tables kernel module.

On most modern distributions such as Debian, Ubuntu, and RHEL, this layer is already active by default, which can be verified with iptables --version, since the output then shows nf_tables instead of legacy. The big advantage is that rules created via iptables-nft are visible through nft list ruleset and can be freely combined with natively written nft rules in the same table, allowing a smooth, low risk transition from pure iptables scripting to native nftables syntax without interrupting operation.


# Check which backend the iptables command currently uses
iptables --version
# iptables v1.8.9 (nf_tables)

# Explicitly switch between legacy and nft backend, Debian/Ubuntu
update-alternatives --set iptables /usr/sbin/iptables-nft
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft

7. Practical example: a complete server firewall with rate limiting

A realistic firewall setup for a Magento hosting server combines default rules, an admin IP set, and rate limiting against SSH brute force attempts in a single, readable configuration file. Rule order still matters, since nftables chains are still evaluated sequentially, just far more efficiently once sets and maps replace dozens of individual rules.

The native limit rate expression is particularly valuable, letting you cap connection rates directly within a rule instead of reaching for a separate hashlimit module with a complex parameter list as in iptables. That makes it straightforward to build a robust, readable firewall configuration that opens HTTP, HTTPS, and SSH deliberately and drops everything else by default.


table inet filter {
  set admin_ips {
    type ipv4_addr
    flags interval
    elements = { 203.0.113.10, 198.51.100.0/28 }
  }

  chain input {
    type filter hook input priority 0; policy drop;

    ct state established,related accept
    iifname lo accept

    tcp dport { 80, 443 } accept
    tcp dport 22 ip saddr @admin_ips accept

    tcp dport 22 ct state new limit rate 5/minute accept
    tcp dport 22 ct state new counter drop
  }
}

8. Monitoring and debugging nftables rule sets in production

For troubleshooting in production, nft list ruleset -a not only shows the active configuration but also exposes internal handle IDs, letting you delete or replace individual rules without reloading the entire rule set. Counters within a rule, as used on the SSH drop rule in the example above, continuously track packet and byte counts and can be inspected with nft list counters to spot suspicious patterns early.

For deeper analysis, nftables also offers native logging expressions that, unlike iptables, are integrated directly into the rule syntax and can be tagged with a specific prefix to unambiguously identify dropped packets in the kernel log. Combined with journalctl -k or a central log aggregator, this makes it possible to trace which rule fired for which packet, which speeds up debugging considerably, especially for more complex set and map based rule sets.


# List the rule set with handle IDs for targeted edits
nft list ruleset -a

# Additionally log dropped SSH packets
nft add rule inet filter input tcp dport 22 ct state new \
  log prefix \"ssh-drop: \" drop

# Search the kernel log for the logged entries
journalctl -k -g ssh-drop

9. Best practices and common pitfalls during migration

The most common mistake during migration is still maintaining separate tables for IPv4 and IPv6, even though the inet address family exists to solve exactly that problem. Anyone writing new rule sets from scratch should consistently use inet tables and only fall back to ip or ip6 where protocol specific logic is genuinely needed, for example ICMP specific rules that use different message types between ICMPv4 and ICMPv6.

Another pitfall involves persistent configuration: unlike iptables, where distributions often ship a dedicated persistence package such as iptables-persistent, nftables typically loads its rule set directly from a file such as /etc/nftables.conf via the systemd unit nftables.service. Changes made only interactively with nft commands are lost on the next reboot unless they are also written into that configuration file, which is why production rule sets should always be loaded from a version controlled file.

Criterion iptables nftables
Rule evaluation Sequential per rule, linear with rule count Bytecode in a kernel VM, efficient even with many rules
IPv4/IPv6 Separate tools iptables and ip6tables Shared inet address family in one table
Large rule volumes One rule per IP or port required Native sets and maps with near constant lookup time
Atomic updates Only as a whole via iptables-restore Default behavior on every nft -f load
Migration path No migration path needed iptables-nft compatibility layer for a gradual switch

Mironsoft

Server administration, Docker hosts, and performance tuning

Linux servers nobody on the team really understands anymore?

We handle setup, hardening, and performance tuning of Linux servers and Docker hosts for Magento deployments, documented and traceable instead of grown and unclear.

Server Audit

Review the existing server configuration for security gaps and performance bottlenecks.

Docker Host Setup

Set up and secure production-ready Docker environments for Magento cleanly.

Monitoring & Tuning

Measure resource usage and tune systemd, kernel, and services with purpose.

10. Summary

nftables Migration

Core benefit

Native sets and maps replace thousands of individual rules at constant performance

Migration tool

iptables-restore-translate converts the whole rule set in a single pass

Transition path

iptables-nft compatibility layer allows a gradual switch without downtime

Biggest pitfall

Separate ip and ip6 tables instead of the unified inet address family

11. FAQ: nftables Migration

1Do I have to rewrite all existing iptables rules by hand?
No, iptables-restore-translate can automatically convert a complete iptables rule set into nftables syntax. In practice only a few special rules with unusual match modules typically need manual follow up.
2Will my existing iptables script still run after switching?
Yes, as long as the iptables-nft compatibility layer is active, classic iptables commands keep working unchanged, but are executed internally through the nftables kernel infrastructure instead of the old legacy x_tables implementation.
3What is the difference between a set and a map in nftables?
A set holds a list of values that a packet field is checked against, for example allowed IP addresses. A map additionally links each value to its own action, so several decisions can be expressed in a single data structure.
4Why should I use the inet address family instead of ip?
With inet, IPv4 and IPv6 rules can be maintained in the same table and chain, avoiding duplicate rule sets and possible inconsistencies between the two protocol versions, which noticeably cuts maintenance effort.
5How do I make sure my nftables rules survive a reboot?
The rule set must be stored in a file such as /etc/nftables.conf, which the systemd unit nftables.service loads automatically at boot with nft -f. Rules set only interactively are otherwise lost on the next reboot.
6Is nftables actually faster than iptables with many rules?
Yes, especially with hundreds or thousands of entries, since sets are implemented as hash tables or balanced trees and offer near constant lookup time, while iptables has to evaluate every rule sequentially.
7Can I run nftables and the iptables-nft layer in production at the same time?
Yes, both access the same nftables kernel infrastructure and can be combined in the same table, allowing a gradual switch from pure iptables scripting to native nft syntax without interrupting operation.
8How do I check which backend my iptables command currently uses?
The command iptables --version shows either nf_tables or legacy in its output. On Debian and Ubuntu, update-alternatives lets you switch explicitly between the two backends.
9What happens if I add rules one by one with individual nft add rule commands?
Each individual nft command is executed atomically on its own, but the same intermediate state risk as with iptables command by command still applies. For a consistent overall rule set, the full configuration should be loaded from a single file with nft -f.
10Does nftables support advanced rate limiting like Fail2ban style scenarios?
Yes, the native limit rate expression allows connection limits per time unit to be defined directly within a rule, and combined with ct state new it can implement brute force protection without any additional kernel module.