How to implement an IPv6 SNAT rule using nftables?

I’m attempting to set up a source NAT rule for IPv6 on my router. I need any outgoing packets on the interface enp1s0 to be modified to have a specific IPv6 address.

Attempts I’ve made:

First Attempt:

nft add rule inet nat postrouting oifname "enp1s0" snat ip6 to 2401:fb00:0:1ff::32d/64

Received an error: “Could not process rule: No such file or directory”

Second Attempt:

nft add rule nat postrouting oifname "enp1s0" snat to 2401:fb00:0:1ff::32d

Received an error: “Could not resolve hostname: Address family for hostname not supported”

Third Attempt:

nft add rule nat postrouting ip6 oifname enp1s0 snat to 2401:fb00:0:1ff::32d

Received an error: “syntax error, unexpected oifname”

Request for assistance:

I would greatly appreciate any guidance on resolving these issues.

you need the ip6 family table, not inet. try nft add rule ip6 nat postrouting oifname "enp1s0" masquerade first to test if ipv6 nat works at all. if that’s good then use snat to 2401:fb00:0:1ff::32d - don’t put the /64 suffix there.

Interesting issue! I’ve been working with ipv6 nat lately too - it’s definitely tricky.

Looking at your attempts, I think you’re mixing up syntax and ipv6 nat works differently than ipv4.

First - does your kernel support ipv6 nat? Not all setups have it enabled by default. Check if ip6_tables and ip6table_nat modules are loaded.

What version of nftables are you running? Older versions had quirky ipv6 support. Check with nft --version

For the actual rule, you might need a separate ip6 table for ipv6 nat instead of the inet family:

nft add table ip6 nat
nft add chain ip6 nat postrouting { type nat hook postrouting priority 100 \; }

Then try your snat rule on that specific table.

But what exactly are you trying to achieve? Prefix translation or just masquerading? Understanding your end goal would help figure out the best approach.

Also, does ip -6 addr show enp1s0 show that target address is actually configured on that interface?

Those syntax errors happen because IPv6 NAT needs specific table and chain setup. You’re trying to add rules to tables that don’t exist yet - been there, done that. Spent hours debugging the same thing when I started with IPv6 SNAT. Here’s what fixed it for me: First, create the ip6 nat table if it’s missing: nft add table ip6 nat nft add chain ip6 nat postrouting { type nat hook postrouting priority 100 \; policy accept \; } Then add your SNAT rule: nft add rule ip6 nat postrouting oifname "enp1s0" snat to 2401:fb00:0:1ff::32d Key differences: use ip6 family, create the nat table first, and drop the /64 prefix from your SNAT target. Also double-check that target IPv6 address is actually assigned to your system with ip -6 addr show. SNAT breaks if the kernel can’t route return traffic through that address.