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.
iptables package 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.
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.
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.
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.
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.
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.
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.
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.
nft -c -f.