Delegate IPv6 ULA to Wireguard peers for NAT6 connectivity

Make sure that allowed IPs include ::/0 in the WireGuard configs on the client side.
You should not need extra routes with source routing disabled and IPv6 masquerading enabled.

I dont understand this sentence. Do you mind try to explain it to me?
How do you "disable" source routing? (AFAIK there is "Source Routing" like routing information which takes also the source and not only the destination into account, and a routing protocol does some math to calculate a path; and in addition the linux kernel route table can have routes for a destination and taking the source in consideration too...)
And even with masq6, don't you need a route for default from ula? (I never bother to use masq6 and consider even my usage of NPT as ugly but the best I can do without a static ipv6 assignment)

Hey there!

So, it turns out my OpenWRT installation was a bit corrupted, and after changing the mSD card for a new one and redoing the configuration as follows:


config interface 'loopback'
    option device 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'

config globals 'globals'
    option ula_prefix 'ddf8:f929:5f71::/48'
    option packet_steering '1'

config device
    option name 'br-lan'
    option type 'bridge'
    list ports 'eth1'
    list ports 'ztrta4adry'
    option stp '1'

config interface 'lan'
    option device 'br-lan'
    option proto 'static'
    option ipaddr '192.168.1.1'
    option netmask '255.255.255.0'
    option ip6assign '64'
    list ip6class 'local'

config interface 'wan'
    option proto 'pppoe'
    option device 'eth0'
    option ipv6 '1'
    list ip6class 'local'
    option delegate '0'

config interface 'wan6'
    option proto 'dhcpv6'
    option device '@wan'
    option reqprefix '64'
    option reqaddress 'try'
    option sourcefilter '0'
    option ip6assign '64'
    list ip6class 'wan6'

config interface 'wg0'
    option proto 'wireguard'
    option private_key 'REDACTED'
    option listen_port '51820'
    list ip6class 'local'
    option ip6assign '64'
    list addresses '10.0.5.1/24'
    list addresses 'fe80::e097:46ff:fef0:2d8e/64'
    list addresses 'fd2d:a278:3852::1/64'

config wireguard_wg0
    option description 'ToastyUltra22'
    option public_key 'M8VDSoxXhBP+Hy3pYYdlx94b7RW1DQ0UticOu9V0OGk='
    option endpoint_port '51820'
    option persistent_keepalive '25'
    option preshared_key 'REDACTED'
    option route_allowed_ips '1'
    option private_key 'REDACTED'
    list allowed_ips '10.0.5.2/32'
    list allowed_ips 'fd2d:a278:3852::2/128'

config wireguard_wg0
    option description 'ToastyUFO'
    option preshared_key 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    option public_key 'GQ9vEK42RjlRCnOrm3SS/Xmf1Gkqdp4ms8CGknF5Kzw='
    list allowed_ips '10.0.5.3/32'
    list allowed_ips 'fd2d:a278:3852::3/128'

config wireguard_wg0
    option description 'Moto One Action de Liz'
    option preshared_key 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    option public_key 'X7dSbHOsnLdlcuB4ZLlfsz7oqwtKhSmaCnakQAtJXB0='
    list allowed_ips '10.0.5.4/32'
    list allowed_ips 'fd2d:a278:3852::4/128'

config wireguard_wg0
    option description 'Liz-PC'
    option public_key 'YL2g4t3zSGAmK82pOj3JjsExz1xKNmnKcDzrZY6733I='
    option preshared_key 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    list allowed_ips '10.0.5.5/32'
    list allowed_ips 'fd2d:a278:3852::5/128'

config wireguard_wg0
    option description 'Moto One Action de Celia'
    option preshared_key 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    option public_key 'HwCzTJShdSN52tEpdvavAEfX5DwU/jgO5fIWyseJ6Bg='
    list allowed_ips '10.0.5.6/32'
    list allowed_ips 'fd2d:a278:3852::6/128'

config device
    option name 'eth1'
    option mtu '1492'
    option mtu6 '1492'

config device
    option name 'br-iot'
    option type 'bridge'
    list ports 'br-lan.2'

config device
    option name 'br-guest'
    option type 'bridge'
    list ports 'br-lan.3'

config interface 'ZeroTier'
    option proto 'none'
    option ip6assign '64'
    list ip6class 'local'
    list ip6class 'wan_6'
    option device 'ztrta4adry'

config device
    option name 'pppoe-wan'
    option type 'tunnel'

config device
    option name 'wg0'

config interface 'wg_usa'
    option proto 'wireguard'
    option private_key 'REDACTED'
    list addresses '10.2.0.2/32'
    option peerdns '0'
    list dns '10.2.0.1'

config wireguard_wg_usa
    option description 'SE-US#1'
    option public_key 'REDACTED'
    option endpoint_host 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    list allowed_ips '0.0.0.0/0'
    list allowed_ips '::/0'

config interface 'wg_uk'
    option proto 'wireguard'
    option private_key 'REDACTED'
    list addresses '10.2.0.2/32'
    option peerdns '0'
    list dns '10.2.0.1'

config wireguard_wg_uk
    option description 'IS-ES#1'
    option public_key 'REDACTED'
    option endpoint_host 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    list allowed_ips '0.0.0.0/0'
    list allowed_ips '::/0'

config interface 'wg_spa'
    option proto 'wireguard'
    option private_key 'REDACTED'
    list addresses '10.2.0.2/32'
    option peerdns '0'
    list dns '10.2.0.1'
    option route_allowed_ips '0'

config wireguard_wg_spa
    option description 'CH-UK#1'
    option public_key 'REDACTED'
    option endpoint_host 'REDACTED'
    option endpoint_port '51820'
    option persistent_keepalive '25'
    list allowed_ips '0.0.0.0/0'
    list allowed_ips '::/0'

config interface 'docker'
    option device 'docker0'
    option proto 'none'
    option auto '0'
    option peerdns '0'
    option ip6assign '64'
    list ip6class 'local'
    list ip6class 'wan_6'

config device
    option type 'bridge'
    option name 'docker0'
    option bridge_empty '1'

Everything works now automagically!

Fortunately I am still using masq6, so no need to mess with NPT for now, but at least regarding the routing itself, everything is peachy now (aside from that, now Docker has problems starting and absolutely no connection to WAN while still using nftables, and for some reason every reboot makes the "/" mount read-only, but those are topics for another day).

Thanks everyone for the help! I'll go ahead now and update the other thread to point to this one.

1 Like

This is an easier way to provide IPv6 connectivity, albeit asymmetric:
https://openwrt.org/docs/guide-user/network/ipv6/ipv6.nat6#command-line_instructions

NPT is generally more error prone and requires at least some prefix, which is not always available, and we also need to consider how to properly update the rules if the prefix is dynamic.

However, if you decide to go down that rabbit hole, try nftables instead of deprecated iptables:
https://openwrt.org/docs/guide-user/firewall/fw3_configurations/fw3_nat#ipv6_npt

Mhm, but my question was not "how to configure NPT" or "how to configure masq6", my questions was about your statement regarding "disable source routing", because AFAIK you can not disable this, as it is a core function of ipv6 routing, with and without getting the source information from a routing protocol or not...

And I don't get your statement and from the wiki, that NPT is somehow hard or complicated or error prone. Its "like" an IPv4 1:1 NAT, without the connection state.
What makes it error prone? You have a route to default, from ula, and setup a single NPT rule. That's all and I fail to see when and how this should cause issues, and what kind of issues. (Yes NPT should only be used in special cases where native IPv6 addressing is not possible, like in this case: You have no static prefix, and a pretty-restraining interface type like wg where you neither can use DHCPv6 or SLAAC. Or you have multiple uplinks but not static prefix which can be routed via both uplinks, and so on...)

uci set network.wan6.sourcefilter=0
uci commit network
ifup wan6
1 Like

Wow. Let me dig into that. Thanks.
(By any chance, do you have other references? And still, I was/am under the impression that "source based routing" is not optional for a "working ipv6 network". The ability to disable it, is Linux specific, isn't it?)

I believe what @vgaetera meant was to disable it on OpenWrt, hence my reference. I am not sure if he referred to any Linux.

1 Like

The only reference I find in the openwrt source is indeed only on the "DHCPv6 Client" part in package/network/ipv6/odhcp6c/files/dhcpv6.sh

So it is not even a "Linux feature". I found some information about the handling of IPv6 Header Options related to Source-Specific / Source-Based Routing but that's a different thing... (then decide an interface not only based on the dst but also on the src without having SSR/SBR information within the Packet Header.)

You probably missed the link I posted above, it makes unicast routing for IPv6 similar to IPv4.

Apparently it is not hard-coded on the side of the router, and there's a UCI option to alter this behavior.

Compared to the method linked above, the probability of user-related errors during configuration is higher, and requirements for IPv6 prefix issued by the ISP are more strict in general, i.e. /128 is not an option, and dynamic prefix requires extra steps to keep it up to date.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.