Docker- og VM-trafikk bak OpenVPN: rute eller omnummerere?
Containere og gjester på en vert med en OpenVPN-klient mister enten returveien eller kolliderer med tunnelprefikset. Tre spørsmål velger løsningen.
Verten surfer gjennom tunnelen, og containeren ved siden av når ingenting. Å publisere en port fra en container som kjører sin egen VPN-klient er verre: forespørselen kommer inn, og svaret forlater aldri verten. Begge er rutingsbeslutninger på verten, og Docker er bare budbringeren.
Tre spørsmål avgjør hvilken av de to du ser på, og de tar omtrent et minutt.
To feil som ser like ut
Den første er et problem med returveien. En publisert port oversettes inn i containeren, forespørselen kommer inn, og svaret rutes av vertens standardrute, som OpenVPN-klienten har pekt på tun0. Svaret forlater en adresse som den eksterne parten ikke forventer, og det blir droppet. Den andre er en prefikskollisjon: Docker sin standardbro eier 172.17.0.0/16, og en bedriftstunnel skyver det samme området.
Den ene rettes med en rutetabell, den andre ved å omnummerere en bro. Å redigere før du vet hvilken som er hvilken, er måten å ødelegge en fungerende container på.
Avgjør med tre spørsmål
Spørsmål én: forsvinner feilen når du stopper VPN-en? Hvis alt virker med tunnelen nede, mistenker du returveien. Spørsmål to: viser ip route show table all det samme prefikset to ganger, én gang på en bro og én gang på tun0? Det er kollisjonen. Spørsmål tre: er den berørte adressen en container, en NAT-gjest eller en broet gjest?
Det tredje spørsmålet betyr noe fordi hver av dem har en annen riktig retting, og å bruke containerrettingen på en libvirt-gjest kaster bort en kveld.
ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'Returvei: en tabell for én kildeadresse
Når containertrafikken må gå ut gjennom det fysiske grensesnittet mens verten selv bruker tunnelen, er kildebasert ruting den minste endringen. Legg til en regel som samsvarer med containerens adresse, og send den til en egen tabell. Ingenting annet på verten flytter seg.
ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10Hver pakke med den adressen som kilde slår opp tabell 10 først, og tabell 10 sender den til broens gateway i stedet for tunnelen.
Bekreft med ip route get 1.1.1.1 from 172.22.0.3. Svaret må navngi broens grensesnitt, ikke tun0. Regler lagt til på denne måten forsvinner ved omstart, så legg dem i enheten eller nettverkskroken som eier containeren.
Samme mønster fungerer for en WireGuard-container, der returveien også trenger en eksplisitt regel.
Prefikskollisjon: omnummerer broen
En rutetabell sender ett prefiks til ett sted. Hvis VPN-en skyver 172.17.0.0/16 mens Docker-broen allerede er der, vinner den laveste metrikken: Docker installerer sin tilknyttede rute med metrikk 0, og den skjøvne ruten kommer inn med 50. Da ser tunnelen ødelagt ut mens Docker fortsetter å virke, eller omvendt, avhengig av installasjonsrekkefølgen. Omnummerer broen i stedet for å kjempe mot metrikken.
{
"bip": "10.200.0.1/24",
"default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}Start Docker på nytt etter endringen og opprett nettverk som er bygget med den gamle poolen på nytt. Å endre metrikken i stedet flytter bare konflikten til neste oppstart.
VM-er trenger igjen et annet svar
En libvirt-gjest på standard NAT-nettverk arver vertens ruting og slutter å nå utenfor når vertens tunnel eier standardruten. Å flytte gjesten til en broet eller macvtap-enhet gir den sin egen vei på det fysiske nettet. I virt-manager legger du til maskinvare, velger Network, setter kilden til macvtap-vertens enhet, beholder virtio som modell og deaktiverer deretter det gamle NAT-grensesnittet.
En macvtap-gjest kan vanligvis ikke nå sin egen vert. Det er forventet atferd og ikke en feil, og det hører hjemme i notatet du legger igjen.
For en gjest som bare trenger vertens LAN, kan leverandørens klient ha den manglende bryteren: med Mullvad gjenoppretter mullvad lan set allow lokal tilgjengelighet uten å røre libvirt. Og når en container bare skal være tilgjengelig gjennom tunnelen, bind den publiserte porten til tunneladressen, -p 10.8.0.5:8080:8080, i stedet for å publisere den på hver adresse.