Wireguard in der Hetzner Cloud

Durch einen meiner Kunden bin ich auf das Wireguard Projekt aufmerksam geworden.

Bei WireGuard handelt es sich um ein sehr simples und doch hochperformantes VPN, welches anders als OpenVPN und Co. direkt auf Linux Kernel Ebene arbeitet. Die Konfiguration beschränkt sich dabei per Interface auf eine einzige Konfigurationsdatei (hier /etc/wireguard/wg0.conf auf server01.example.tld)

[Interface]
Address = fd86:ea04:1115:0:5054:ff:fefd:e128/64
SaveConfig = false
ListenPort = 51820
PrivateKey = QKFKDqpg6oDFbnhq/WfNhExbi5IqTU+8GDOLb7E+9HU=

[Peer]
PublicKey = p+PusqlRIQ1cvdNIvfXXEBlf2puVHkfk/vGv9KCn9FQ=
Endpoint = server02.example.tld:51820
AllowedIPs = fd86:ea04:1115:0:11:32ff:fe27:3e3e/128

Ich nutze WireGuard um ein internes Netz über mein Heimnetzwerk und mehrere Clouds (Azure, AWS, Hetzner) hinweg ein internes IPv6 Netz zu spannen. Über dieses Netz laufen diverse Backend Dienste (wie Prometheus, Icinga, Consul, Vault, Nomad), die nicht direkt von extern erreichbar sein müssen.
Der große Vorteil liegt für mich darin, das die Kommunikation dezentral (also direkt von System zu Zielsystem) erfolgt. Ich muss somit keinen zentralen VPN-Server betreiben, der unter Umständen einen SPOF in meinem Setup darstellen könnte.

Vor kurzem habe ich dann einige Systeme in der Hetzner Cloud in Betrieb genommen (Ubuntu 18.04 LTS). Diese wollte Ich natürlich ebenfalls in meinen WireGuard Mesh mit aufnehmen.

Hier hatte ich jedoch das Problem, das nach dem Starten des WireGuard Tunnels kein IPv6 Verkehr außerhalb des Tunnels mehr möglich war. Lediglich ping6 funktionierte noch, vorausgesetzt man hat das Default Interface (Option -I eth0) mit angegeben.

Da das ganze auf anderen Ubuntu Systemen reibungslos funktionierte, war schnell klar das das Hetzner Basis Image schuld sein muss.

Nach langem Troubleshooting des IPv6 Routings konnte ich das Problem dann auch ausfindig machen.
Hetzner konfiguriert die Netzwerkkonfiguration mittels cloud-init folgendermaßen vor (/etc/network/interfaces.d/50-cloud-init.cfg).

...
auto eth0:0
iface eth0:0 inet6 static
address 2a01:1234:1234:1234::1/64
gateway fe80::1
post-up route add -net :: netmask 0 gw fe80::1%eth0 || true
pre-down route del -net :: netmask 0 gw fe80::1%eth0 || true

Diese Konfiguration ist aber kaputt. Die Pre- und Post-Scripte führen zu einem Fehler. Weiterhin führt das Alias Interface (eth0:0) bzw. das fehlen einer IPv6 Adresse auf eth0 dazu, das mit der Konfiguration einer weiteren IPv6 Adresse (auf einem anderen Interface) kein IPv6 mehr funktioniert.

Die Lösung ist die Konfiguration auf das empfohlene Schema umzustellen und die IPv6-Adresse auf eth0 umzuziehen.

...
auto eth0
iface eth0 inet6 static
address 2a01:1234:1234:1234::1
netmask 64
gateway fe80::1

Alternativ kann auch komplett auf die „Legacy Konfiguration“ via /etc/network/interfaces verzichtet werden.

Ein Nachteil von Wireguard ist das das nötige Kernel Modul aktuell noch nicht nativ im Kernel von gängigen Linux Distributionen vorhanden ist. Daher ist die Installation via DKMS (Dynamic Kernel Module Support) nötig. In Zukunft soll sich das aber noch ändern.