Värden surfar genom tunneln och containern bredvid når ingenting. Att publicera en port från en container som kör sin egen VPN-klient är värre: förfrågan kommer in och svaret lämnar aldrig värden. Båda är routingbeslut på värden, och Docker är bara budbäraren.

Tre frågor avgör vilket av de två du tittar på, och de tar ungefär en minut.

Två fel som ser likadana ut

Det första är ett problem med returvägen. En publicerad port översätts in i containern, förfrågan kommer in, och svaret routas av värdens standardrutt, som OpenVPN-klienten har pekat på tun0. Svaret lämnar en adress som motparten inte förväntar sig, och det släpps. Det andra är en prefixkollision: Dockers standardbrygga äger 172.17.0.0/16 och en företagstunnel trycker in samma område.

Det ena åtgärdas med en routingtabell, det andra genom att numrera om en brygga. Att redigera innan du vet vilket som är vilket är hur man förstör en fungerande container.

Bestäm med tre frågor

Fråga ett: försvinner felet när du stoppar VPN:en? Om allt fungerar med tunneln nere, misstänk returvägen. Fråga två: visar ip route show table all samma prefix två gånger, en gång på en brygga och en gång på tun0? Det är kollisionen. Fråga tre: är den drabbade adressen en container, en NAT-gäst eller en bryggad gäst?

Den tredje frågan spelar roll eftersom var och en har en annan korrekt åtgärd, och att tillämpa containeråtgärden på en libvirt-gäst slösar bort en kväll.

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

Returväg: en tabell för en källadress

När containerns trafik måste gå ut genom det fysiska gränssnittet medan värden själv använder tunneln, är källbaserad routing den minsta ändringen. Lägg till en regel som matchar containerns adress och skicka den till en egen tabell. Inget annat på värden flyttar sig.

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

Varje paket vars källa är den adressen tittar först i tabell 10, och tabell 10 skickar det till bryggans gateway i stället för tunneln.

Bekräfta med ip route get 1.1.1.1 from 172.22.0.3. Svaret måste namnge bryggans gränssnitt, inte tun0. Regler som läggs till så här försvinner vid omstart, så lägg dem i den enhet eller nätverkskrok som äger containern.

Samma mönster fungerar för en WireGuard-container, där returvägen också behöver en uttrycklig regel.

Prefixkollision: numrera om bryggan

En routingtabell skickar ett prefix till en plats. Om VPN:en trycker in 172.17.0.0/16 medan Dockers brygga redan är där, vinner den lägre metriken: Docker installerar sin anslutna rutt med metrik 0, och den intryckta rutten kommer in med 50. Då ser tunneln trasig ut medan Docker fortsätter att fungera, eller tvärtom, beroende på installationsordningen. Numrera om bryggan i stället för att slåss med metriken.

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

Starta om Docker efter ändringen och återskapa nätverk som byggts med den gamla poolen. Att ändra metriken flyttar bara konflikten till nästa start.

Virtuella maskiner behöver återigen ett annat svar

En libvirt-gäst på standard-NAT-nätet ärver värdens routing och slutar nå ut när värdens tunnel äger standardrutten. Att flytta gästen till en bryggad eller macvtap-enhet ger den en egen väg på det fysiska nätet. I virt-manager lägger du till maskinvara, väljer Network, ställer in källan på macvtap-värdenheten, behåller virtio som modell och inaktiverar sedan det gamla NAT-gränssnittet.

En macvtap-gäst kan vanligtvis inte nå sin egen värd. Det är förväntat beteende och inte ett fel, och det hör hemma i anteckningen du lämnar.

För en gäst som bara behöver värdens LAN kan leverantörens klient ha den saknade brytaren: med Mullvad återställer mullvad lan set allow lokal nåbarhet utan att röra libvirt. Och när en container bara ska vara nåbar genom tunneln, bind den publicerade porten till tunneladressen, -p 10.8.0.5:8080:8080, i stället för att publicera den på varje adress.

Relaterade artiklar