Verschachteltes VPN: Welcher Tunnel trägt die äußere Verbindung?
Ein innerer Tunnel braucht einen äußeren Pfad zu seinem Endpunkt. Zwei in falscher Reihenfolge gestartete Clients erzeugen einen Routenkonflikt, deshalb zuerst die Verschachtelung in Ordnung bringen.
Zwei gleichzeitig laufende VPN-Clients ergeben keinen verschachtelten Tunnel; sie ergeben zwei Tunnel und einen Streit über das Routing. Ein verschachtelter Tunnel liegt vor, wenn die Verbindung des inneren Clients zu seinem eigenen Server selbst vom äußeren Tunnel getragen wird, und das ist eine Anordnung, die man absichtlich herstellt. Stimmt sie, sieht der innere Server die Adresse des äußeren Servers; stimmt sie nicht, verbindet sich ein Client still um den anderen herum neu. Drei Bedingungen entscheiden, ob die Verschachtelung echt oder zufällig ist.
Drei Bedingungen entscheiden über die Verschachtelung
Die erste ist, welcher Endpunkt welchen Pfad braucht. Nenne die Adresse des inneren Servers, nenne die Adresse des äußeren Servers und stelle ausdrücklich fest, dass der innere Server nur über den äußeren Tunnel erreichbar ist. Alles Weitere folgt aus diesem Satz, auch welche Routen in welche Tabelle gehören.
Die zweite ist, ob du den Pfad auf jeder Ebene sehen kannst. Wenn du den Kernel nicht fragen kannst, welche Route ein bestimmtes Ziel nehmen würde, schließt du die Kette aus einer abschließenden Exit-IP, und genau dieser Beleg kann eine Verschachtelung nicht von einem Zufall unterscheiden.
Die dritte ist, was passiert, wenn der äußere Tunnel wegfällt. Der innere Tunnel kann mit ihm stoppen, sich über das gewöhnliche Netz neu verbinden oder blockiert bleiben, bis der äußere Pfad zurückkehrt, und alle drei sind vertretbare Vorgehensweisen. Sie sind nicht dieselbe Vorgehensweise, und das Standardverhalten der meisten Clients ist die zweite. Ein Client, der seinen Endpunkt über das physische Netz neu verbindet und dabei eine gesunde Verbindung anzeigt, ist der häufigste Weg, auf dem eine beabsichtigte Kette stillschweigend zu zwei unabhängigen Tunneln wird.
Bedingung eins: welcher Endpunkt welchen Pfad braucht
ip route get 203.0.113.10 beantwortet diese Frage direkt: Der Befehl gibt die Route, die Quelladresse und die Schnittstelle aus, die der Kernel für dieses Ziel gerade verwenden würde.
Führe ihn für den inneren Server aus, bevor der innere Client startet, und danach noch einmal, und vergleiche. Wechselt die Antwort von der physischen Schnittstelle zur Schnittstelle des äußeren Tunnels, ist die Verschachtelung in diesem Moment echt. Ändert sie sich nicht, verbindet sich der innere Client direkt, egal was das Dashboard sagt. Wiederhole das für die Adresse des äußeren Servers, die weiterhin über die physische Schnittstelle aufgelöst werden muss, denn eine Route, die beide Endpunkte rekursiv einfängt ist der Fehler, der die Maschine vollständig aus dem Netz nimmt.
Bedingung zwei: den Pfad auf jeder Ebene prüfen
Die Routenauswahl ist bei einem modernen Client mehr als die Haupttabelle. Policy-Rules können markierte Pakete in eine andere Tabelle schicken, ein Client kann seinen Socket an eine Schnittstelle binden, und ein Container oder Namespace hat ohnehin eigene Tabellen. Mit ip rule und ip route show table all findest du heraus, welcher dieser Fälle gerade greift.
Ein Client, der SO_MARK auf seinen eigenen Socket setzt oder so konfiguriert ist, dass er sich an ein bestimmtes Gerät bindet, umgeht die Standardroute, die du eingerichtet zu haben glaubst. Das ist eine Funktion und kein Fehler, und es bedeutet, dass nur eine Prüfung verlässlich ist, die im selben Namespace wie der Client läuft. Laufen die Clients in Containern, führe die Prüfungen in diesen Containern statt auf dem Host aus.
Bedingung drei: was passiert, wenn der äußere Tunnel wegfällt
Fehlerverhalten braucht eine Entscheidung, keinen Standard. Schreibe auf, was mit dem inneren Tunnel geschehen soll, wenn der äußere verschwindet, und bringe dann die Clients dazu, genau das zu tun.
Die Optionen sind konkret. Den inneren Client zu stoppen, wenn der äußere Pfad wegfällt, ergibt eine saubere Kette und einen offensichtlichen Ausfall. Ihn sich direkt neu verbinden zu lassen ergibt Verfügbarkeit und entfernt stillschweigend die Eigenschaft, für die die Kette gebaut wurde. Bis zur Rückkehr des äußeren Pfads zu blockieren ist die strengste und im Betrieb lästigste Variante, weil jedes Flattern des äußeren Tunnels zu einem sichtbaren Vorfall wird.
Teste alle drei mit harmlosem Verkehr und einem absichtlichen Ausfall des äußeren Tunnels, denn die Konfiguration zu lesen sagt dir nicht, welche Variante du hast. Beende den äußeren Tunnel, beobachte, was der innere Client tut, und prüfe die Route erneut, während er weg ist. Bringe den äußeren Tunnel dann zurück und bestätige, dass sich die Kette neu bildet, statt den inneren Client auf dem direkten Pfad zu lassen, den er in der Zwischenzeit gewählt hat.
Was die Kette nicht liefert
Zusätzliche Ebenen fügen Endpunkte, Schlüssel und Fehlerarten hinzu; sie fügen keine Anonymitätsgarantie hinzu und sie machen es dem äußeren Betreiber nicht unmöglich zu sehen, dass ein Tunnel existiert. Jede Aussage darüber, wovor die Verschachtelung schützt, muss den Beobachter nennen, vor dem sie schützt.
Das Ergebnis ist ein kurzes Dokument und keine funktionierende Verbindung: welcher Endpunkt welchen Pfad nutzt, was bei einem Ausfall des äußeren Tunnels passiert und die drei Befehle, die den aktuellen Zustand zeigen. Die Weiterleitungsdokumentation von strongSwan ist eine nützliche Referenz dafür, wie Tunnelverkehr auf einem Linux-Host zwischen Schnittstellen weitergeleitet wird. Führe die Prüfungen nach jedem Client-Upgrade erneut aus, denn die Standards, die deine Kette erzeugt haben, sind kein Vertrag. Ein verschachtelter Tunnel, den du nicht prüfen kannst, ist ein Gerücht mit Statusanzeige.