Docker- en VM-verkeer achter OpenVPN: routeren of hernummeren?
Containers en gasten op een host met een OpenVPN-client verliezen de retourroute of botsen met het tunnelprefix. Drie vragen kiezen de oplossing.
De host surft door de tunnel en de container ernaast bereikt niets. Een poort publiceren vanuit een container die zijn eigen VPN-client draait is erger: het verzoek komt aan en het antwoord vertrekt nooit. Beide zijn routeringsbeslissingen op de host, en Docker is alleen de boodschapper.
Drie vragen bepalen welk van de twee je ziet, en ze kosten ongeveer een minuut.
Twee fouten die er hetzelfde uitzien
De eerste is een probleem met de retourroute. Een gepubliceerde poort wordt naar de container vertaald, het verzoek komt aan, en het antwoord wordt gerouteerd via de standaardroute van de host, die de OpenVPN-client naar tun0 heeft gericht. Het antwoord vertrekt vanaf een adres dat de externe peer niet verwacht, en het wordt weggegooid. De tweede is een prefixbotsing: de standaardbrug van Docker bezit 172.17.0.0/16 en een bedrijfstunnel duwt hetzelfde bereik.
De ene wordt met een routeringstabel opgelost, de andere door een brug te hernummeren. Bewerken voordat je weet welke welke is, is hoe je een werkende container sloopt.
Beslis met drie vragen
Vraag één: verdwijnt de fout als je de VPN stopt? Als alles werkt met de tunnel neer, verdenk dan de retourroute. Vraag twee: toont ip route show table all hetzelfde prefix twee keer, één keer op een brug en één keer op tun0? Dat is de botsing. Vraag drie: is het getroffen adres een container, een NAT-gast of een gebrugde gast?
De derde vraag telt omdat elk een andere juiste oplossing heeft, en de containeroplossing op een libvirt-gast toepassen kost een avond.
ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'Retourroute: een tabel voor één bronadres
Wanneer het verkeer van de container via de fysieke interface naar buiten moet terwijl de host zelf de tunnel gebruikt, is routering op basis van de bron de kleinste wijziging. Voeg een regel toe die bij het adres van de container past en stuur die naar een aparte tabel. Niets anders op de host beweegt.
ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10Elk pakket waarvan de bron dat adres is, raadpleegt eerst tabel 10, en tabel 10 stuurt het naar de gateway van de brug in plaats van de tunnel.
Bevestig met ip route get 1.1.1.1 from 172.22.0.3. Het antwoord moet de interface van de brug noemen, niet tun0. Regels die zo worden toegevoegd verdwijnen bij een herstart, dus zet ze in de unit of netwerkhaak die de container bezit.
Hetzelfde patroon werkt voor een WireGuard-container, waar de antwoordroute ook een expliciete regel nodig heeft.
Prefixbotsing: hernummer de brug
Een routeringstabel stuurt één prefix naar één plek. Als de VPN 172.17.0.0/16 duwt terwijl de brug van Docker er al is, wint de laagste metriek: Docker installeert zijn verbonden route op metriek 0, en de geduwde route komt aan op 50. Dan lijkt de tunnel stuk terwijl Docker blijft werken, of andersom, afhankelijk van de installatievolgorde. Hernummer de brug in plaats van met de metriek te vechten.
{
"bip": "10.200.0.1/24",
"default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}Herstart Docker na de wijziging en maak netwerken opnieuw aan die met de oude pool zijn gebouwd. De metriek wijzigen verplaatst het conflict alleen naar de volgende start.
VM's hebben weer een ander antwoord nodig
Een libvirt-gast op het standaard NAT-netwerk erft de routering van de host en bereikt het buiten niet meer zodra de tunnel van de host de standaardroute heeft. De gast naar een gebrugd of macvtap-apparaat verplaatsen geeft hem zijn eigen pad op het fysieke netwerk. Voeg in virt-manager hardware toe, kies Network, zet de bron op het macvtap-hostapparaat, houd virtio als model en deactiveer daarna de oude NAT-interface.
Een macvtap-gast kan zijn eigen host meestal niet bereiken. Dat is verwacht gedrag en geen fout, en het hoort in de notitie die je achterlaat.
Voor een gast die alleen het LAN van de host nodig heeft, heeft de client van de leverancier misschien de ontbrekende schakelaar: met Mullvad herstelt mullvad lan set allow de lokale bereikbaarheid zonder libvirt aan te raken. En wanneer een container alleen via de tunnel bereikbaar moet zijn, bind de gepubliceerde poort aan het tunneladres, -p 10.8.0.5:8080:8080, in plaats van hem op elk adres te publiceren.