How to migrate iptables rules to nftables

Migrating iptables rules to nftables moves a reviewed firewall policy from save-format iptables rules into a native nft ruleset that can be loaded, listed, and persisted through /etc/nftables.conf. The migration should preserve the allowed and blocked traffic paths before the old rules are retired.

The iptables-restore-translate utility reads an iptables-save file and emits equivalent nft commands for rules it can translate. The translated file still needs review because unsupported matches or targets can appear as comments, and loading native nftables rules beside another firewall manager can create unexpected packet-filter behavior.

Direct iptables rules should own the host policy before the replacement file is loaded. Keep a console or second administrative session open, save a rollback file first, repeat the export and translation with ip6tables when IPv6 is filtered, and avoid replacing rules that are managed by ufw, firewalld, Docker, or another controller without migrating through that controller.

Steps to migrate iptables rules to nftables:

  1. Open a recovery path before changing firewall ownership.

    A native nftables load can interrupt SSH, VPN, forwarding, or application traffic if translated rules omit a required allow path. Keep console access or a second administrative session ready before applying the new file.

  2. Check which iptables backend produced the active rules.
    $ iptables --version
    iptables v1.8.11 (nf_tables)

    If the host reports (legacy), export from that same active legacy command family. If it reports (nf_tables), confirm that the host is not also managed by native nft files, ufw, firewalld, or Docker before replacing policy. Related: How to check the active iptables backend

  3. Save the current IPv4 rules as the rollback file.
    $ sudo iptables-save > ~/iptables-before-nftables.rules

    Keep this file available until the migrated rules have passed traffic tests and persistence checks.

  4. Save the current native nftables ruleset when one already exists.
    $ sudo nft list ruleset > ~/nftables-before-migration.nft

    An empty file or empty ruleset is normal on hosts that only used legacy iptables before migration.

  5. Translate the saved iptables rules into nft syntax.
    $ sudo iptables-restore-translate -f ~/iptables-before-nftables.rules > ~/nftables-from-iptables.nft
  6. Review the translated file before loading it.
    # Translated by iptables-restore-translate v1.8.11 on Sat Jun  6 01:44:19 2026
    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 INPUT iifname "lo" tcp dport 2222 counter accept
    add rule ip filter INPUT iifname "lo" tcp dport 8080 counter drop
    # Completed on Sat Jun  6 01:44:19 2026

    Do not load the file until every commented translation line has been rewritten or deliberately removed. A commented drop, reject, rate-limit, set, or owner match can change the policy after migration.

  7. Build the target /etc/nftables.conf file from the translated rules.
    $ sudoedit /etc/nftables.conf

    Use a complete file for the tables this host owns.

    flush ruleset
    # Translated by iptables-restore-translate v1.8.11 on Sat Jun  6 01:44:19 2026
    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 INPUT iifname "lo" tcp dport 2222 counter accept
    add rule ip filter INPUT iifname "lo" tcp dport 8080 counter drop
    # Completed on Sat Jun  6 01:44:19 2026

    Use flush ruleset only when this file is intended to own the full nftables ruleset. On hosts where another service owns tables or sets, migrate through that service or narrow the file to the table ownership model already in use.

  8. Check the nftables file without applying it.
    $ sudo nft -c -f /etc/nftables.conf

    No output means the file parsed successfully. Fix syntax errors before any live firewall state is changed.

  9. Load the native ruleset during the maintenance window.
    $ sudo nft -f /etc/nftables.conf
  10. List the loaded ruleset and confirm the expected chains and rules are present.
    $ sudo nft list ruleset
    table ip filter {
    	chain INPUT {
    		type filter hook input priority filter; policy accept;
    		iifname "lo" tcp dport 2222 counter packets 0 bytes 0 accept
    		iifname "lo" tcp dport 8080 counter packets 0 bytes 0 drop
    	}
    
    	chain FORWARD {
    		type filter hook forward priority filter; policy accept;
    	}
    
    	chain OUTPUT {
    		type filter hook output priority filter; policy accept;
    	}
    }
  11. Test one traffic path that should remain allowed.
    $ nc -zv -w 3 server.example.com 2222
    Connection to server.example.com 2222 port [tcp/*] succeeded!

    Replace the host and port with a service that the old iptables policy allowed, such as SSH from a management network or an application listener from an allowed client.

  12. Test one traffic path that should remain blocked.
    $ nc -zv -w 3 server.example.com 8080
    nc: connect to server.example.com port 8080 (tcp) timed out: Operation now in progress

    A blocked-path test proves more than a successful allow test because it confirms the deny side of the old policy also survived translation.

  13. Enable the nftables service after the live rules pass traffic tests.
    $ sudo systemctl enable --now nftables.service

    On Ubuntu and Debian hosts, the nftables service loads /etc/nftables.conf immediately and at boot. Run this only after the file has passed sudo nft -c -f /etc/nftables.conf and live traffic tests.

  14. Clear the failed native ruleset only if rollback is required.
    $ sudo nft flush ruleset

    Do not flush a host where another active service owns native nftables tables unless that service is part of the rollback plan.

  15. Restore the saved iptables rollback file.
    $ sudo iptables-restore < ~/iptables-before-nftables.rules

    Rollback returns the saved iptables policy to the active backend selected by the iptables command. Disable or stop nftables.service first if it would reload the failed native file during reboot or service restart. Related: How to restore iptables rules from a file