Problemlösung: Asymmetrisches Routing durch Wireguard VPN

Für die Bereitstellung von öffentlichen IPv6-Adressen in nicht-IPv6-Netzwerken und zur Absicherung meiner Kommunikation in fremden Netzwerken betreibe ich ein eigenes kleines, Wireguard-basiertes VPNWährend des Testbetriebs stellte sich heraus, dass ich zwar mit IPv6-Zieladressen im Internet ohne Probleme kommunizieren konnte - doch die Kommunikation zu IPv6-Ressourcen, die innerhalb meiner eigener Infrastruktur liegen, schlug fehl. Genauer: TCP-basierte Kommunikation schlug fehl. Nach etwas Debugging mittels tcpdump und einer Skizze meiner Infrastruktur war die Ursache schnell klar:

Ohne es gleich zu bemerken, wurden TCP-Anfragen an meine eigenen Services anders geroutet als die dazugehörigen Antworten. Im Folgenden will ich das Problem und mögliche Lösungen erklären.

Eines vorweg: Das Problem ist ein relativ spezifisches und tritt u.U. nur dann auf, wenn VPN-Server und angesprochener Service (in meinem Fall Nextcloud) im selben Netz-Segment betrieben werden.

Sehen wir uns zunächst einmal die Netzstruktur an:

Der betreffende Teil meiner Serverinfrastruktur befindet sich hinter einer zentralen Firewall “FW”. Er besteht zum einen aus dem Wireguard VPN-Server, der ein öffentliches IPv6-Subnetz an die Clients verteilt - und meinem Nextcloud Server, der ebenso wie das primäre Netzwerinterface meines VPN-Servers im selben Subnetz hängt.

Wenn Ressourcen im Internet angesprochen werden, die außerhalb meiner eigenen Infrastruktur liegen, sieht der Weg der TCP-Requests (rot) und TCP-Responses (grün) wie folgt aus:

Symmetrische Routen
Symmetrische Routen

Man spricht hier von symmetrischem Routing: Der Weg der Anfrage und der Antworten sind (zumindest innerhalb meines Setups) identisch - beide Male ist die Firewall involviert. Sie protokolliert die ausgehende Verbindung (rot) und legitimiert daraufhin die eingehende Verbindung (grün) für eine Antwort.

Etwas anders sieht es aus, wenn ich meinen Nextcloud-Dienst anspreche: Weil sich der VPN-Server im selben Subnetz befindet wie der Nextcloud- erver, wird die Anfrage zum Nextcloud Server nicht über das default-Gateway / die Firewall geschickt, sondern auf dem direkten Wege über das LAN. Der Nextcloud Server beobachtet eine eingehende Verbindung aus einem IP-Adressbereich, der nicht seinem eigenen entspricht (… dem IPv6 VPN Bereich) und antwortet daraufhin nicht wieder direkt auf dem LAN, sondern schickt die Antwort über die Firewall. Diese hat allerdings die ursprüngliche Anfrage nicht mitbekommen und blockiert die “herrenlose” Antwort ohne zugehörige Anfrage. Die Antwort kommt also nie an.

Asymmetrische Routen
Asymmetrische Routen

Kern des Problems ist, dass der Weg der Anfrage ein anderer als der der Antwort ist und die Sicherheitsmechanismen der FW anspringen.

Zur Lösung eignen sich drei Wege - ich habe mich für den letzten entschieden:

  1. Auf dem Nextcloud Server: Antworten auf Anfragen aus dem VPN-Adressbereich nicht über die FW routen, sondern direkt über das LAN bzw zum VPN-Server.
  2. Auf der FW: Das Verhalten der FW ändern und auch Antworten durchlassen, für die keine Anfrage protokolliert wurde
  3. Auf dem VPN-Server: Anfragen auch dann über die Firewall leiten, wenn sie an ein Ziel im lokalen Netzsegment gehen.

Lösung #1 ist unpraktisch, weil dazu nicht nur der Nextcloud Server angepasst werden muss, sondern auch alle weiteren lokalen Server, die potenziell über das VPN angesprochen werden. Funktioniert, ist aber nicht “schön”.

Lösung #2 gefällt nicht, weil hierzu ein Sicherheitsmechnismus der Firewall deaktiviert werden muss.

Lösung #3 bringt zwar ein paar Umwege mit sich - im lokalen Netzwerk spielen diese bzgl. Performance allerdings eine untergeordnete Rolle und fallen bei mir nicht ins Gewicht. Daher habe ich mich für diese Lösung entschieden.

Asymmetrische Routen
Asymmetrische Routen

Implementierung

Wie schon im verwandten Beitrag “Network settings for second Wireguard-based default gateway” habe ich auf dem VPN-Server eine weitere Routingtabelle angelegt:

echo "101 wg6" >> /etc/iproute2/rt_tables

Meine Wireguard-Konfiguration habe ich um einige PostUp und PostDown Definitionen ergänzt:

# Route traffic to services on LAN via another routing table
# to avoid asymmetric shortcut via LAN instead of FW.
Table = off
PostUp = ip -6 route add 2001:DB8:2::1/128 dev ens3 table wg6
PostUp = ip -6 route add default via 2001:DB8:2::1 dev ens3 table wg6
PostUp = ip -6 route add 2001:DB8:1::/50 dev wg6 table wg6
PostUp = ip -6 rule add from 2001:DB8:1::/50 table wg6
PostDown = ip -6 route del 2001:DB8:2::1/128 dev ens3 table wg6
PostDown = ip -6 route del default via 2001:DB8:2::1 dev ens3 table wg6 
PostDown = ip -6 route del 2001:DB8:1::/50 dev wg6 table wg6
PostDown = ip -6 rule del from 2001:DB8:1::/50 table wg6

… wobei

  • 2001:DB8:1::/50 das VPN-Netz ist und
  • 2001:DB8:2::1 die IP-Adresse der Firewall / des Gateways
  • ens3 das Netzwerkinterface zu Firewall / Gateway

Aus dem VPN lassen sich nun sowohl interne Server als auch externe problemlos erreichen.