Network settings for second Wireguard-based default gateway

Situation: One of my servers is located at my home. It’s connected to the internet via two different interfaces at the same time:

  • Physical Interface: Connected to Deutsche Telekom ISP via DSL / landline.
  • Virtual Wireguard VPN interface: Connected to one of my data center servers, has a public IPv6 address.

The “data center server” acts as a gateway for my home server and routes a static IPv6 address to it. This setup lets me reach my home server via a static and public IP address, although my DSL provider does not assign a static IPv6 subnet to my landline. (But that is subject to another story … ;-) ).

After finishing the setup, I ran into the problem of asymmetric routing: Packets addresses to my static IPv6 address (and thus routed via the Wireguard VPN) did arrive at my home server, but the response packets were not send back the same way: They were routed via my Deutsche Telekom landline and therefore originated from another source IP address, which the original requester did not expect.

Two routes to the rest of the internet: A connection originating from the blue link was responded on the black link.
Two routes to the rest of the internet: A connection originating from the blue link was responded on the black link.

Fortunately this is easy to fix:

A new routing table in addition to the default routing table needs to be configured. We’ll call the new routing table with priority 1 rt_wg6 and add it to /etc/iproute2/rt_tables:

echo "1 rt_wg6" >> /etc/iproute2/rt_tables

After that, the Wireguard interface configuration for the wg6 connection needs to be changed:

[Interface]
PrivateKey = kLtn7A9eDqpUXqLCHeu2S8C7r843jnO8yyxBtKBXQmE=
Address = 2001:0DB8:33c:0100::2/56
Table = off
PostUp = ip -6 route add 2001:0DB8:33c:0100::/56 dev %i src 2001:0DB8:33c:0100::2 table rt_wg6
PostUp = ip -6 route add default via 2001:0DB8:33c:0100::1 dev %i table rt_wg6
PostUp = ip -6 rule add from 2001:0DB8:33c:0100::2/128 table rt_wg6
PostUp = ip -6 rule add to 2001:0DB8:33c:0100::2/128 table rt_wg6
PostDown = ip -6 route del 2001:0DB8:33c:0100::/56 dev %i src 2001:0DB8:33c:0100::2 table rt_wg6
PostDown = ip -6 route del default via 2001:0DB8:33c:0100::1 dev %i table rt_wg6
PostDown = ip -6 rule del from 2001:0DB8:33c:0100::2/128 table rt_wg6
PostDown = ip -6 rule del to 2001:0DB8:33c:0100::2/128 table rt_wg6

[Peer]
[...]
  • 2001:0DB8:33c:0100::2: IP-address of the home server (on its Wireguard interface wg6)
  • 2001:0DB8:33c:0100::1: IP-address of the gateway server at the data center (on its Wireguard interface wg6)

Diverging from the usual configuration, the Table = off and Post* settings make the dual-gateway setup work: By default, the wg-quick utility creates routes using the default routing table - which causes the issues mentioned above. By setting Table = off we tell wg-quick to let us set our own routes in another routing table - the rt_wg6 table.

%i is a placeholder for the Wireguard interface - wg6 in my case. The PostDown settings are the exact opposite of the PostUp lines. That way, the routing configuration is cleaned up when Wireguard is shut down.

After a reboot my network interfaces now behave correctly: Connections coming from the Wireguard interface are now responded to via the Wireguard interface while connection requests originating from the device itself (or the landline) pass the main interface to my home network.