WireGuard and IPv6 Source Address Selection (was: ipv6 tunnels and babel's source specific routing)

Samuel Holland samuel at sholland.org
Sat Nov 10 18:41:06 CET 2018


Hi,

This isn't quite the same situation you're in (I'm not using a routing daemon),
but I have also had issues with WireGuard and IPv6 source address selection, and
I thought I'd share my solution for the benefit of the list. This might be the
"some better way to deprioritize a given set of ipv6 addrs" you're looking for.

My VPN topology consists of two fixed sites with native IPv6, plus some road
warriors without IPv6. Site A has a DHCPv6 IA-PD subnet we'll call
2605:aaaa:aaaa:aa::/56, and Site B has a DHCPv6 IA-PD subnet we'll call
2600:bbbb:bbbb:bbb::/60. Because Site A was the original site, and it has the
larger prefix, I use a /64 from that subnet ("2605:aaaa:aaaa:aacc::/64") to
connect all of the WireGuard peers in a mesh. So my configuration looks
something like this (ignoring IPv4), where the first IP address given for each
peer is the one assigned (with prefix length 64) to wg0:

    [Peer]
    PublicKey = <Site_A_Router_Key>
    AllowedIPs = 2605:aaaa:aaaa:aacc::10/128, 2605:aaaa:aaaa:aa::/56

    [Peer]
    PublicKey = <Site_B_Router_Key>
    AllowedIPs = 2605:aaaa:aaaa:aacc::20/128, 2600:bbbb:bbbb:bbb::/60

    [Peer]
    PublicKey = <Road_Warrior_1_Key>
    AllowedIPs = 2605:aaaa:aaaa:aacc::81/128

    [Peer]
    PublicKey = <Road_Warrior_2_Key>
    AllowedIPs = 2605:aaaa:aaaa:aacc::82/128

This works great for every machine *except* the router at Site B, which also
happens to be my main workstation. Linux always chooses 2605:aaaa:aaaa:aacc::20
as the source address when sending packets to the Internet, and of course that
gets dropped by my ISP, because they only delegated me 2600:bbbb:bbbb:bbb::/60.

I tried to set `preferred_lft 0` on 2605:aaaa:aaaa:aacc::20, but that caused
other issues (it's been a couple of months so I don't remember the details). The
solution actually turned out to be really simple:

    ip addrlabel add prefix 2605:aaaa:aaaa:aa::/56 label 100

One of the rules for IPv6 source address selection is to prefer source addresses
with the same label as the destination. Normally, the whole publicly routable
IPv6 space is one label (while link-local, loopback, IPv4-mapped, etc. are
unique), but you can create arbitrary labels. Just pick any ID that's not
already in use (`ip addrlabel` shows the list of existing labels).

Having Site A's subnet on its own label does exactly what I want. Traffic to
Site A from the router at Site B always uses its address from wg0, and traffic
*outside* Site A's subnet *never* uses the address from wg0.

Hope this helps,
Samuel

On 11/08/18 20:57, Dave Taht wrote:
> I figured out the first two bits of using source specific routing for
> ipv6 with wireguard...
> 
> The first trick was to watch what wg-quick wanted to do and change it.
> So I setup my vpn client (deep within
> my network) thusly:
> 
> [Interface]
> #Address = 2600:8211:e001:9300::2/60
> ListenPort = 51820
> PrivateKey = neveryoumind
> 
> [Peer]
> PublicKey = notdoingthat
> AllowedIPs = 2600:8211:e001:9300::/60, ::/0
> Endpoint = tun.taht.net:51820
> 
> This tells wireguard to let any ipv6 address through and treat it like
> a default route. We don't really want this but I fix this later.
> 
> The server is setup similarly, but no ::/0 and an address of ::1/60
> 
> Then I changed the default startup to look like this:
> 
> #!/bin/sh
> ip link add wg0 type wireguard
> wg setconf wg0 /etc/wireguard/wg0.conf
> # preferred_lft 0 makes sure you don't use this address for anything
> you don't explicitly bind to
> # Otherwise *because* it is static, with a preferred_lft of forever,
> it gets chosen as
> # a default ipv6 addr over the dynamic ipv6 addresses. I only want the vpn for
> # specific tools...
> ip address add 2600:8211:e001:9300::2/60 dev wg0 preferred_lft 0
> ip link set mtu 1420 dev wg0
> ip link set wg0 up
> ip route add 2600:8211:e001:9300::/60 dev wg0
> # the default line generated by wg-quick inserts a default route for everything
> # which disables my native ipv6 addrs and routing
> # The trick - note the from and the proto
> ip -6 route add ::/0 from 2600:8211:e001:9300::/60 dev wg0 proto 48
> 
> then I setup babeld.conf to have
> 
> redistribute proto 48 allow
> 
> which exports that "from default" to the rest of my network without
> doing a default default route that RA picks up
> 
> I can then do stuff anywhere else on my net (running babel rfc61236bis) , like
> 
> ip address add 2600:8211:e001:9301::1/64 dev whichever preferred_lft 0
> 
> which gives me a valid_lft of forever... and
> 
> this lets me use my native, dynamic, ipv6 ips from comcast in the general case,
> and the vpn tunnel'd ipv6 address ranges only when I explicitly specify it.
> 
> I have no idea if dhcpv6-pd can be configured (with a valid_lft of a
> lot, constantly renewed, and a prefeered of 0) this way or hnetd, or
> if there was some better way
> to deprioritize a given set of ipv6 addrs, but...
> 
> Now that I have a whole /56 I can finally fiddle more with hnetd
> again. This also gives me cheap failover if one of my gws goes down...


More information about the WireGuard mailing list