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.1

Dva 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.

RepairWho owns itWhat it costs
Renumber the container networkYouRecreates the network, restarts services, invalidates literal addresses in configs and scripts
Exclude your range from the tunnelNetwork teamChanges what every laptop sees, needs a change request and a client profile update
Reach the service through a published portYou and the clientOne 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/24

Uzmite 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:

  1. ip route get s hosta, koristeći stvarnu adresu kontejnera.
  2. Zahtjev iz drugog kontejnera, da dokažete da je sama usluga zdrava.
  3. curl -sv http://127.0.0.1:8080/ s klijenta s uključenim tunelom, zatim traceroute -n do adrese kontejnera sa stroja na LAN-u.
  4. sysctl net.ipv4.conf.all.rp_filter ako 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.

Povezani članci