nftables Migration: iptables and ipset to Sets - 夜莺博客

nftables Migration: iptables and ipset to Sets

Moving from iptables to nftables is usually described as a syntax change, but the real work is the data structures: ipset lists become native nftables sets, and many rule chains collapse into a single verdict map. Getting that part right shrinks rulesets dramatically and removes the need for a separate ipset daemon. This guide covers the translation path, the parity gaps you have to work around, NAT equivalents, and how to make the final ruleset survive a reboot.

Start with the translation tools, not by hand

# rule-by-rule translation of a saved iptables ruleset
iptables-save > rules.v4
iptables-restore-translate -f rules.v4 > rules.nft

# sets
ipset save > sets.ipset
ipset-translate restore < sets.ipset >> rules.nft

# single rule while you learn the syntax
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
nft 'add rule ip filter input tcp dport 22 accept'

ipset-translate (since ipset 7.12) maps set types into nftables set data types, often producing concatenated types: a hash:net,port,net set becomes a set of type ipv4_addr . inet_service . ipv4_addr. The utility writes into a dummy inet global table, so expect to tidy the output into your own tables and chains.

Sets and verdict maps

table inet filter {
  set mgmt_hosts {
    type ipv4_addr
    elements = { 10.10.0.5, 10.10.0.6, 192.0.2.0/24 }
  }

  map port_policy {
    type inet_service : verdict
    elements = { 22 : accept, 80 : accept, 3306 : drop }
  }

  chain input {
    type filter hook input priority filter; policy drop;
    iif lo accept
    ct state established,related accept
    ip saddr @mgmt_hosts tcp dport { 22, 443 } accept
    tcp dport vmap @port_policy
  }
}

Note the two features that make nftables worth the migration: inline anonymous sets ({ 22, 443 }) for compact rules, and vmap verdict maps that return the action directly from a lookup instead of jumping through chains. A policy that needed dozens of iptables rules with -m set matches often becomes one or two lines.

The negated-element gap

ipset supports nomatch entries; nftables sets do not. The documented workaround is to split the list into a positive set and a negated set and combine them in a rule:

ip saddr @pos_set ip saddr != @neg_set accept

NAT, masquerade and persistence

table inet nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    oifname "eth0" masquerade
  }
  chain prerouting {
    type nat hook prerouting priority dstnat; policy accept;
    iifname "eth0" tcp dport 8080 dnat to 10.10.20.10:80
  }
}
# make it persistent
nft list ruleset > /etc/nftables.conf
systemctl enable --now nftables

# atomic replace of a live ruleset from a file
nft -f /etc/nftables.conf.new
nft list ruleset -a   # show handles for editing single rules

Loading a whole file with -f replaces rules atomically, which is why nftables is far easier to manage with configuration management than iptables-restore was. The -a flag prints rule handles so you can delete or insert a specific rule without flushing a chain.

Migration checklist

  • Table family – use table inet for rules that should apply to IPv4 and IPv6 together; a rule in table ip silently ignores IPv6 traffic.
  • Conntrack – the equivalent of -m state is ct state; keep an early ct state established,related accept to avoid re-evaluating the policy for every packet.
  • Counters – add counter to a rule to get hit counts, then read them with nft list ruleset; the counters are per rule, not per anonymous set element.
  • Application compatibility – Docker, Kubernetes and libvirt still insert their own chains; on a host where the container runtime manages rules, leave its tables alone.
  • Rollback plan – keep the iptables ruleset file until you have verified DNAT/SNAT behaviour end to end, not just a ping test.

Related: VyOS firewall and NAT examples, Linux network namespaces and veth, and Linux network tuning with sysctl.

原文链接:https://wiki.nftables.org/wiki-nftables/index.php/Moving_from_ipset_to_nftables