[PATCH] fw4: add masquerade-prefix snat type

Jonas Lochmann openwrt at jonaslochmann.de
Mon Oct 27 09:25:08 PDT 2025


Am Sun, Oct 26, 2025 at 03:47:00PM +0100, schrieb Jonas Lochmann:
> Am Sun, Oct 26, 2025 at 10:40:25AM -0300, schrieb Luiz Angelo Daros de Luca:
> > nft add rule inet fw4 srcnat_netmap oifname "$DEVICE" snat ip6 prefix
> > to ip6 saddr map { $ip6addr : $ip6prefix/$ip6prefix_mask }

This is equivalent to the snat with the bit operations. It just uses
some native code instead of nftables bytecode:

> for (i = 0; i < len / sizeof(__be32); i++) {
>   netmask = ~(range->min_addr.ip6[i] ^ range->max_addr.ip6[i]);
>   new_addr.ip6[i] &= ~netmask;
>   new_addr.ip6[i] |= range->min_addr.ip6[i] & netmask;
> }

So the "snat ip6 prefix" has the prefix internally as ip range from that
a netmask is extracted by checking if min and max are the same for a
particular bit. Bits from the netmask are cleared and then or-ed with the
netmask. [1]

For comparision the readable nftables action from my patch:

> let target = "snat ip6 to ip6 saddr and " + suffix_mask + " or " + base_addr;

The nftables code is based on the idea that a new range of IPs can be
provided where any IP can be chosen. The "prefix" just calls the
mentioned function that calculates the new_addr and then sets minimum
and maximum of it to the same value for this particular invocation.

This shows that the name masquerade-prefix is actually a good choice for
this feature. One could call it snat-prefix but the prefix is (at fw4
level) replaced by the assigned prefix and masquerade replaces the src
ip just with the one assigned to the interface (altough this at nft
level).

[1] https://github.com/torvalds/linux/blob/v6.17/net/netfilter/nft_nat.c#L93



More information about the openwrt-devel mailing list