Docker kontejner nedostupan na VPN-u? Usporedite podmreže
Docker dodjeljuje podmrežu koju VPN također prisvaja. Usporedite dva plana adresa, pa odaberite popravak koji preživi ponovno povezivanje.
Kontejneri odgovaraju na uredskom LAN-u, a zatim prestanu odgovarati u trenutku kada se poveže korporativni VPN. Ništa u kontejneru nije promijenjeno: nema restarta, nema ažuriranja slike, nema izmjene konfiguracije. Promijenila se tablica usmjeravanja hosta, gdje ruta koju je tunel dodao sada pokriva adresu koju je Docker dodijelio. Prije nego što uredite podmrežu ili zatražite izuzetak od VPN-a, stavite oba plana adresa jedan uz drugi, jer popravci koštaju vrlo različito vrijeme.
Pročitajte rutu prije nego što promijenite konfiguraciju
Počnite s mrežom koju je Docker zaista izgradio. IPAM blok je plan adresa, a podmreža je redak koji je važan:
docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]Compose prema zadanim postavkama dodjeljuje /16 svakom novom projektu, pa dvije usluge mogu stati unutar raspona od 65,536 adresa. Ta širina je razlog zašto su preklapanja česta: slučajno odabran /16 dovoljno je velik da proguta stranicu do koje dolazite kroz tunel, i nitko to ne primijeti dok se tunel ne podigne.
Zatim usporedite odabir rute za jednu adresu kontejnera, jednom s isključenim tunelom i jednom s uključenim:
ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1Dva oblika odgovora vode na različita mjesta. Ako izlaz navodi tun0, wg0 ili drugi tunelski uređaj, VPN prefiks je barem jednako specifičan kao ruta mosta i paket nikada ne stiže do kontejnera. Ako se i dalje navodi most, host može doći do kontejnera, a vaša je greška filtriranje, DNS ili povratna putanja koja pada samo u jednom smjeru.
Zašto je sudar /16 lako pogoditi
Docker uzima mreže mosta iz privatnih bazena, a zadani bazen dolazi iz bloka 172.16.0.0/12 u isječcima od /16. Korporativne mreže često koriste isti privatni prostor, a VPN za daljinski pristup gura te prefikse na svakog klijenta koji se poveže. Kada obje strane vjeruju da posjeduju 172.18.0.0/16, jedna tablica usmjeravanja drži dvije proturječne tvrdnje.
Dužina prefiksa odlučuje pobjednika, a ne redoslijed kojim se rute pojavljuju. Tunel koji gura 10.0.0.0/8 ne pobjeđuje rutu mosta 172.18.0.0/16, jer je /8 manje specifičan. Tunel koji gura 172.18.0.0/16, ili 172.18.5.0/24 unutar njega, pobjeđuje. Zato jedan laptop radi na uredskoj mreži, a pada na hotelskom Wi-Fi-ju s istim VPN-om: klijent prima različite prefikse.
Ista tablica upravlja i suprotnim smjerom. Kontejner koji treba interni host na 10.8.4.20 šalje paket na svoj gateway mosta, a host ga zatim usmjerava u tunel. Ta putanja obično radi jer host obavlja NAT, ali pada kada korporativna strana prihvaća samo VPN adresu laptopa ili kada filtriranje povratne putanje odbaci asimetrični odgovor.
Usporedite tri popravka
Postoje samo tri izlaza, i razlikuju se po tome tko ih mora odobriti i što se kvari dok primjenjujete jedan od njih.
| Repair | Who owns it | What it costs |
|---|---|---|
| Renumber the container network | You | Recreates the network, restarts services, invalidates literal addresses in configs and scripts |
| Exclude your range from the tunnel | Network team | Changes what every laptop sees, needs a change request and a client profile update |
| Reach the service through a published port | You and the client | One port only, no direct container-to-container routing across the tunnel |
Prenumeriranje je jedini popravak koji možete završiti bez tikete, zato se većina tekstova tu zaustavlja. Jeftin je na mladom projektu i skup kada alat za migraciju ili spremljeni string veze pokaže na doslovnu adresu. Prebrojite te reference prije nego što uredite YAML, ne poslije.
Izuzetak od tunela najčišći je odgovor kada se preklapanje nalazi u rasponu koji vaša tvrtka zaista posjeduje. Ujedno je i najsporiji, i beskoristan je za izvođača koji ne može promijeniti profil klijenta. Objavljeni port ili mali obrnuti proxy izbjegava raspravu: klijent razgovara s adresom koju tunel već ispravno usmjerava, i samo taj port mora biti dostupan.
Pričvrstite raspon namjerno
Za jedan projekt deklarirajte podmrežu u compose datoteci da projekt prestane crpiti iz zajedničkog bazena:
networks:
default:
ipam:
config:
- subnet: 10.201.7.0/24Uzmite taj raspon iz registra koji vodi vaš tim, a ne iz primjera koji ste našli pretražujući. Provjerite ga prema prefiksima koje VPN gura, kućnim LAN-ovima s kojih ljudi rade i drugim kontejnerskim mrežama na istom hostu. Zatim planirajte ponovno stvaranje, jer postojeća mreža zadržava staru podmrežu: docker compose down, zatim up -d. docker network rm odbija dok su krajnje točke priključene, i svaki ipv4_address unos u datoteci mora pasti unutar novog raspona.
Za mreže koje Docker stvara sam, postavite bazen daemona u /etc/docker/daemon.json:
{
"default-address-pools": [
{ "base": "10.201.0.0/16", "size": 24 },
{ "base": "10.202.0.0/16", "size": 24 }
]
}Bazen se primjenjuje na mreže stvorene nakon ponovnog pokretanja daemona, a mostovi koji već postoje zadržavaju svoje adrese. To je zgodno i lako se zaboravlja, pa tretirajte stari projekt kao da se još preklapa dok netko ne ponovno stvori njegovu mrežu. Dockerova dokumentacija o umrežavanju mehanizma opisuje pravila dodjele ako trebate braniti bazen na pregledu.
Linux most i Docker Desktop padaju različito
Na Linux hostu kontejneri sjede na mostovima u imenskom prostoru hosta. Jedna tablica odlučuje o svemu, pa je gore navedena usporedba cijela priča: pročitajte rutu mosta, pročitajte rutu tunela i vidite koja pobjeđuje za stvarnu adresu kontejnera.
Docker Desktop stavlja kontejnere iza VM-a s vlastitim NAT-om. Host uopće nema rutu do adrese kontejnera; do usluge dolazi kroz objavljeni port, obično vezan na 127.0.0.1. VPN klijent zato može pokvariti uslugu bez ikakvog preklapanja podmreža, bilo instaliranjem rute za interni raspon VM-a, bilo blokiranjem loopback prometa dok je tunel povezan. Ako ip route get na hostu prijavi da nema rute do adrese kontejnera, to je očekivano, a ne greška.
Praktična posljedica je gdje prvo gledate. Na Linuxu počnite od tablice usmjeravanja. Na Desktopu počnite od objavljenog porta i pravila vatrozida VPN klijenta, pa provjerite sudara li se interna podmreža VM-a s nečim što tunel gura.
Provjerite s uključenim tunelom
Ponovno povežite VPN dvaput prije nego što to proglasite popravljenim, jer profil koji gura rute pri povezivanju i povlači ih pri odspajanju može izgledati ispravno nakon prvog pokušaja. Zatim pokrenite provjere koje klijent zaista izvodi:
ip route gets hosta, koristeći stvarnu adresu kontejnera.- Zahtjev iz drugog kontejnera, da dokažete da je sama usluga zdrava.
curl -sv http://127.0.0.1:8080/s klijenta s uključenim tunelom, zatimtraceroute -ndo adrese kontejnera sa stroja na LAN-u.sysctl net.ipv4.conf.all.rp_filterako zahtjev stigne do hosta ali odgovor nestane.
Na kraju, upišite odabrani raspon u isti registar iz kojeg ste ga uzeli, s datumom i projektom koji ga posjeduje. Sljedeće preklapanje doći će iz projekta koji nitko nije dokumentirao, a jedina obrana je da je raspon rezerviran namjerno, a ne izvučen slučajno.