Der Host surft durch den Tunnel, und der Container daneben erreicht nichts. Einen Port aus einem Container zu veröffentlichen, der seinen eigenen VPN-Client betreibt, ist schlimmer: Die Anfrage kommt an, und die Antwort geht nie hinaus. Beides sind Routingentscheidungen auf dem Host, und Docker ist nur der Bote.

Drei Fragen entscheiden, welchen der beiden Fälle Sie vor sich haben, und sie dauern etwa eine Minute.

Zwei Fehler, die gleich aussehen

Der erste ist ein Problem des Rückwegs. Ein veröffentlichter Port wird in den Container übersetzt, die Anfrage kommt an, und die Antwort wird über die Standardroute des Hosts geroutet, die der OpenVPN-Client auf tun0 gerichtet hat. Die Antwort verlässt eine Adresse, die das entfernte Gegenüber nicht erwartet, und wird verworfen. Der zweite ist eine Präfikkollision: Dockers Standard-Bridge besitzt 172.17.0.0/16, und ein Firmen-Tunnel schiebt denselben Bereich.

Der eine wird mit einer Routing-Tabelle behoben, der andere durch Umnummerieren einer Bridge. Vorher zu bearbeiten, bevor man weiß, welcher Fall vorliegt, ist der Weg, einen funktionierenden Container zu zerstören.

Entscheiden Sie mit drei Fragen

Frage eins: Verschwindet der Fehler, wenn Sie das VPN stoppen? Wenn mit abgeschaltetem Tunnel alles funktioniert, verdächtigen Sie den Rückweg. Frage zwei: Listet ip route show table all dasselbe Präfix zweimal auf, einmal auf einer Bridge und einmal auf tun0? Das ist die Kollision. Frage drei: Ist die betroffene Adresse ein Container, ein NAT-Gast oder ein gebrückter Gast?

Die dritte Frage zählt, weil jeder Fall eine andere richtige Lösung hat, und die Containerlösung auf einen libvirt-Gast anzuwenden kostet einen Abend.

ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'

Rückweg: eine Tabelle für eine Quelladresse

Wenn der Verkehr des Containers über die physische Schnittstelle hinausgehen muss, während der Host selbst den Tunnel nutzt, ist quellbasiertes Routing die kleinste Änderung. Fügen Sie eine Regel hinzu, die auf die Adresse des Containers passt, und schicken Sie sie in eine eigene Tabelle. Sonst bewegt sich nichts auf dem Host.

ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10

Jedes Paket, dessen Quelle diese Adresse ist, sieht zuerst Tabelle 10 nach, und Tabelle 10 schickt es zum Gateway der Bridge statt in den Tunnel.

Prüfen Sie mit ip route get 1.1.1.1 from 172.22.0.3. Die Antwort muss die Bridge-Schnittstelle nennen, nicht tun0. So hinzugefügte Regeln verschwinden beim Neustart, also legen Sie sie in die Unit oder den Netzwerk-Hook, dem der Container gehört.

Dasselbe Muster funktioniert für einen WireGuard-Container, bei dem auch der Antwortweg eine ausdrückliche Regel braucht.

Präfikkollision: Nummerieren Sie die Bridge um

Eine Routing-Tabelle schickt ein Präfix an einen Ort. Wenn das VPN 172.17.0.0/16 schiebt, während Dockers Bridge schon dort ist, gewinnt die niedrigere Metrik: Docker legt seine verbundene Route mit Metrik 0 an, die geschobene Route kommt mit 50 an. Dann wirkt der Tunnel defekt, während Docker weiterläuft, oder umgekehrt, je nach Installationsreihenfolge. Nummerieren Sie die Bridge um, statt gegen die Metrik zu kämpfen.

{
  "bip": "10.200.0.1/24",
  "default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}

Starten Sie Docker nach der Änderung neu und legen Sie Netzwerke neu an, die mit dem alten Pool gebaut wurden. Die Metrik stattdessen zu ändern verlagert den Konflikt nur auf den nächsten Start.

VMs brauchen wieder eine andere Antwort

Ein libvirt-Gast im Standard-NAT-Netz erbt das Routing des Hosts und erreicht das Außen nicht mehr, sobald der Host-Tunnel die Standardroute besitzt. Den Gast auf eine gebrückte oder macvtap-Schnittstelle umzustellen gibt ihm seinen eigenen Weg im physischen Netz. In virt-manager fügen Sie Hardware hinzu, wählen Network, setzen die Quelle auf das macvtap-Hostgerät, behalten virtio als Modell und deaktivieren dann die alte NAT-Schnittstelle.

Ein macvtap-Gast kann seinen eigenen Host normalerweise nicht erreichen. Das ist erwartetes Verhalten und kein Fehler, und es gehört in die Notiz, die Sie hinterlassen.

Für einen Gast, der nur das LAN des Hosts braucht, hat der Client des Anbieters vielleicht den fehlenden Schalter: Mit Mullvad stellt mullvad lan set allow die lokale Erreichbarkeit wieder her, ohne libvirt anzufassen. Und wenn ein Container nur über den Tunnel erreichbar sein soll, binden Sie den veröffentlichten Port an die Tunneladresse, -p 10.8.0.5:8080:8080, statt ihn auf jeder Adresse zu veröffentlichen.

Ähnliche Artikel