Translate iptables Rules to nftables Without Applying Them
Before you migrate a firewall from iptables to nftables, iptables-translate lets you preview every rule change on paper first. You will turn an iptables command or a saved ruleset into native nftables syntax, inspect the result, and keep the live firewall untouched until you have actually reviewed it. The installed tools here are from iptables 1.8.10-3ubuntu2 and use the nf_tables backend.
The route
Jump straight to the step you need, or tick off Done means at the end.
- Time: 15 to 30 minutes for a small ruleset; a larger production firewall needs its own review and test window.
- You need: the
iptablespackage and, for the full workflow,nft. Translation itself normally runs as an ordinary user, though reading a protected save file or querying a live firewall may need elevated privileges.
Safety boundary
These commands are text converters. They do not change the kernel firewall. The later nft -f command does change live state, so do not run it until the generated file has been reviewed and you have a recovery plan sitting ready.
1. Check which translator is installed
xtables-translate describes the family, but the installed commands expose the input dialect directly. Use iptables-translate for IPv4 commands, ip6tables-translate for IPv6 commands, and the matching restore command for a saved ruleset:
$ command -v iptables-translate ip6tables-translate iptables-restore-translate
/usr/sbin/iptables-translate
/usr/sbin/ip6tables-translate
/usr/sbin/iptables-restore-translate
$ iptables-translate --version
iptables-translate v1.8.10 (nf_tables)
$ dpkg-query -W -f='${Package} ${Version}\n' iptables
iptables 1.8.10-3ubuntu2
Checkpoint
The version output should name the command you will actually use. Formatting can shift between versions, so treat the output above as an example from this machine, not a fixed promise.
2. Translate one IPv4 command
Pass the old iptables arguments straight after the translator name. This example describes a new TCP connection to port 22 being accepted on the IPv4 input chain:
$ iptables-translate -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
nft 'add rule ip filter INPUT tcp dport 22 ct state new counter accept'
The result is an nft command shown as text; the translator never executes it. The ip filter table tells you this is IPv4. An IPv6 translation uses ip6 instead.
Read the output before copying it into a ruleset. Check for the expected family, table, chain, match conditions and verdict. A successful translation is not proof the rule expresses the security policy you actually intended.
3. Translate an IPv6 command separately
Use the IPv6 command for IPv6 syntax. Swap in real interface names from your host; the names below are placeholders only:
$ ip6tables-translate -A FORWARD -i eth0 -o eth3 -p udp -m multiport --dports 111,222 -j ACCEPT
nft 'add rule ip6 filter FORWARD iifname "eth0" oifname "eth3" meta l4proto udp udp dport { 111, 222 } counter accept'
Do not assume translating the IPv4 rules also covers IPv6. Translate and review both families, then check whether your host also runs bridge rules through ebtables; the installed package ships ebtables-translate for that dialect too.
Checkpoint
Keep the generated output in a review file if you need to compare it against the original policy later. No privileged command is required just to produce this text.
4. Export a complete ruleset first
For a real migration, start from a saved ruleset rather than retyping individual commands. Save the IPv4 rules with iptables-save; reading firewall state may need sudo:
$ sudo iptables-save > /path/to/iptables-save.txt
$ sed -n '1,80p' /path/to/iptables-save.txt
Saving is read-only, but the file can contain addresses, interface names and other operational detail, so protect it like configuration data. For IPv6, use ip6tables-save and keep that output in a separate file.
If you cannot read the live firewall yourself, get a trusted export from its owner instead. Do not invent missing chains or policies just to make a partial file look complete.
5. Convert the saved file to nftables syntax
Use iptables-restore-translate with -f and redirect the output to a new file:
$ iptables-restore-translate -f /path/to/iptables-save.txt > /path/to/ruleset.nft
$ sed -n '1,80p' /path/to/ruleset.nft
# Translated by iptables-restore-translate v1.8.10 on ...
add table ip filter
add chain ip filter INPUT { type filter hook input priority 0; policy accept; }
add chain ip filter FORWARD { type filter hook forward priority 0; policy accept; }
add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }
add rule ip filter FORWARD tcp dport 22 ct state new counter accept
For an IPv6 export, use ip6tables-restore-translate; its output should use ip6 table declarations. The restore translators understand the syntax that iptables-save and ip6tables-save emit; they are not general-purpose converters for arbitrary firewall text someone hands you.
Review the whole file, not just its rules. Check default policies, custom chains, comments, counters, NAT behaviour, and every rule flagged with an unsupported or partially supported extension. The man page calls out unsupported extensions as a known limitation, so stop and investigate rather than let a match quietly vanish.
6. Validate the generated file without changing the live firewall
Inspect the file as text first, and keep the original export sitting beside it. You can ask nft to parse a file without applying it, using check mode:
$ nft -c -f /path/to/ruleset.nft
A successful check normally produces no output and returns status 0. Confirm that explicitly:
$ nft -c -f /path/to/ruleset.nft
$ printf 'nft check status: %s\n' "$?"
nft check status: 0
Depending on the nftables build and host permissions, the check may still need access to netfilter state. If it reports cache initialization failed: Operation not permitted, repeat the read-only check with the minimum privilege required, for example sudo nft -c -f /path/to/ruleset.nft. That grants access for validation only; it does not apply the file.
This checks nft syntax and some semantic detail. It does not prove the policy is safe, that every old extension has an equivalent, or that another service will not replace the rules later. Test in an isolated host or maintenance window before you touch a production firewall migration.
7. Apply only after a recovery plan
Warning
Applying a ruleset can interrupt SSH, traffic forwarding and services. A mistake here can lock you out. Make sure you have console or out-of-band access, a known-good original export, and a tested way back to the previous firewall before running:
$ sudo nft -f /path/to/ruleset.nft
$ sudo nft list ruleset
The first command changes live state and needs elevated privileges; the second reads it back so you can compare active tables and chains against the reviewed file. If the result is wrong, use your platform's documented rollback procedure and the original firewall export. Never improvise a flush over a remote session: sudo nft flush ruleset removes the active nftables rules and can cut off access immediately.
Common traps
- Confusing translation with application. The translator only prints commands; a later nft invocation is what actually changes state.
- Checking one address family. IPv4 and IPv6 each need their own translation and review.
- Using the wrong input form. Command translators take an iptables-style command line; restore translators take save-format input.
- Trusting a clean parse. Syntax validation cannot catch an incorrect policy, or an unsupported extension that never made it into the output.
- Overwriting the evidence. Use a new output file so the original save stays available for comparison and recovery.
Done means
- Versions recorded: the installed iptables version and translator family.
- Every family translated: IPv4, IPv6 and any bridge rules in scope, with the matching commands.
- File reviewed and checked: the generated nftables file passed
nft -c -f. - Originals kept: the save files and an access-safe rollback path are both retained.
- Applied carefully: any live application happened in a controlled window, console access on hand.