[PATCH] fw4: add masquerade-prefix snat type

Luiz Angelo Daros de Luca luizluca at gmail.com
Sun Oct 26 06:40:25 PDT 2025


Hi Jonas,

>
> I want to continue this topic. For those who don't remember a short summary:
>
> - this is for use in combination with mwan3 to keep individual addresses
>   for the internal devices with IPv6

I also did the same thing a couple of years ago using hotplug scripts.
When you have multiple ISPs, sometimes you need to rewrite the prefix
when the internal source address does not match the interface mwan3
selected, either because one link is now down or there is a rule that
forces that traffic to a specific interface.

There is another use case without multiple ISP or mwan3. When the
delegated prefix is too small for the number of internal networks, you
can translate the prefix from a specific ULA to the public prefix. In
my case, the ISP only offers a single /64 prefix (it shouldn't), not
enough for an additional guest network. In this case, you'll also need
to rewrite the default route from ULA as it is, by design, not
routable to the internet. I know that I'm abusing ULA but it gets the
job done as ULA is still treated as a public address by the endpoints.

> - this is NOT NPTv6 and NPTv6 would not work; devices know their public
>   IPs and a stateless aproach never knows if a particular reply packet
>   must be rewritten and to which prefix it must be rewritten (the hosts
>   in the internal network have IPs (plural) and could have used any of
>   them to start the outbound connection)

The last time I tested NPTv6 it broke the conntrack. So, you either do
the prefix translation or the statefull firewall, not both.

> > +                                                     if (best_prefix != null) {
> > +                                                             let base_addr = apply_mask(best_prefix.addr, best_prefix.mask);
> > +                                                             let suffix_mask = to_inverse_mask(best_prefix.bits, true);
> > +                                                             let target = "snat ip6 to ip6 saddr and " + suffix_mask + " or " + base_addr;

I didn't try the patch in a real device but it looks like it is using
a different approach than the one I'm using. In my case, I have:

nft add rule inet fw4 srcnat_netmap oifname "$DEVICE" snat ip6 prefix
to ip6 saddr map { $ip6addr : $ip6prefix/$ip6prefix_mask }

I don't know if it is better or worse but it explicitly cites the
prefix in the rule.

Regards,

Luiz



More information about the openwrt-devel mailing list