Kontajnery odpovedajú v kancelárskej LAN a potom prestanú odpovedať v okamihu, keď sa pripojí firemná VPN. V kontajneri sa nič nezmenilo: žiadny reštart, žiadna aktualizácia obrazu, žiadna úprava konfigurácie. Zmenila sa smerovacia tabuľka hostiteľa, kde trasa pridaná tunelom teraz pokrýva adresu, ktorú Docker pridelil. Skôr než upravíte podsieť alebo požiadate o výnimku z VPN, položte oba plány adries vedľa seba, pretože opravy stoja veľmi rozdielne množstvo času.

Prečítajte si trasu skôr, než zmeníte konfiguráciu

Začnite sieťou, ktorú Docker skutočne postavil. Blok IPAM je plán adries a podsieť je ten riadok, na ktorom záleží:

docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]

Compose predvolene pridelí /16 každému novému projektu, takže dve služby sa môžu zmestiť do rozsahu 65,536 adries. Práve táto šírka je dôvod, prečo sú prekryvy časté: náhodne zvolený /16 je dosť veľký na to, aby pohltil lokalitu, ku ktorej sa dostanete cez tunel, a nikto si to nevšimne, kým tunel nenabehne.

Potom porovnajte výber trasy pre jednu adresu kontajnera, raz s vypnutým tunelom a raz so zapnutým:

ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1

Dva tvary odpovede vedú na rôzne miesta. Ak výstup uvádza tun0, wg0 alebo iné tunelové zariadenie, prefix VPN je prinajmenšom rovnako konkrétny ako trasa mosta a paket sa nikdy nedostane ku kontajneru. Ak stále uvádza most, hostiteľ sa ku kontajneru dostane a vaša chyba je filtrovanie, DNS alebo návratová cesta, ktorá zlyháva len v jednom smere.

Prečo je kolízia /16 ľahko dosiahnuteľná

Docker berie mostové siete zo súkromných fondov a predvolený fond pochádza z bloku 172.16.0.0/12 v kúskoch /16. Firemné siete často používajú ten istý súkromný priestor a VPN so vzdialeným prístupom tlačí tieto prefixy každému klientovi, ktorý sa pripojí. Keď obe strany veria, že vlastnia 172.18.0.0/16, jedna smerovacia tabuľka obsahuje dva protichodné nároky.

O víťazovi rozhoduje dĺžka prefixu, nie poradie trás. Tunel tlačiaci 10.0.0.0/8 neprekoná trasu mosta 172.18.0.0/16, pretože /8 je menej konkrétny. Tunel tlačiaci 172.18.0.0/16 alebo 172.18.5.0/24 vnútri neho ju prekoná. Preto jeden laptop funguje v kancelárskej sieti a zlyháva na hotelovom Wi-Fi s tou istou VPN: klient dostáva rôzne prefixy.

Tá istá tabuľka riadi aj opačný smer. Kontajner, ktorý potrebuje interného hostiteľa na 10.8.4.20, pošle paket na svoju mostovú bránu a hostiteľ ho potom smeruje do tunela. Táto cesta zvyčajne funguje, pretože hostiteľ robí NAT, ale zlyhá, keď firemná strana prijíma iba VPN adresu laptopu, alebo keď filtrovanie spätnej cesty zahodí asymetrickú odpoveď.

Porovnajte tri opravy

Existujú len tri východiská a líšia sa tým, kto ich musí schváliť a čo sa pokazí, kým jednu aplikujete.

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

Prečíslovanie je jediná oprava, ktorú dokážete dokončiť bez tiketu, a preto sa väčšina textov zastaví tu. V mladom projekte je lacné a drahé sa stane, keď migračný nástroj alebo uložený spojovací reťazec ukazuje na doslovnú adresu. Spočítajte tie odkazy pred úpravou YAML, nie po nej.

Výnimka z tunela je najčistejšia odpoveď, keď prekryv leží v rozsahu, ktorý vaša firma skutočne vlastní. Je aj najpomalšia a je nepoužiteľná pre dodávateľa, ktorý nemôže zmeniť profil klienta. Publikovaný port alebo malý reverzný proxy obídu spor: klient komunikuje s adresou, ktorú tunel už smeruje správne, a dostupný musí byť len ten port.

Pripnite rozsah zámerne

Pre jeden projekt deklarujte podsieť v súbore compose, aby projekt prestal čerpať zo zdieľaného fondu:

networks:
  default:
    ipam:
      config:
        - subnet: 10.201.7.0/24

Vezmite ten rozsah z registra, ktorý vedie váš tím, nie z príkladu, ktorý ste našli pri hľadaní. Skontrolujte ho voči prefixom, ktoré tlačí VPN, domácim sieťam, z ktorých ľudia pracujú, a ostatným sieťam kontajnerov na tom istom hostiteľovi. Potom naplánujte opätovné vytvorenie, pretože existujúca sieť si zachováva svoju starú podsieť: docker compose down, potom up -d. docker network rm odmieta, kým sú pripojené koncové body, a každý záznam ipv4_address v súbore musí spadať do nového rozsahu.

Pre siete, ktoré Docker vytvára sám, nastavte fond démona v /etc/docker/daemon.json:

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

Fond sa vzťahuje na siete vytvorené po reštarte démona a mosty, ktoré už existujú, si zachovajú svoje adresy. To je pohodlné a ľahko zabudnuteľné, preto považujte starý projekt za stále sa prekrývajúci, kým niekto nevytvorí jeho sieť znova. Dockerova sieťová dokumentácia jadra opisuje pravidlá prideľovania, ak potrebujete fond obhájiť pri revízii.

Linuxový most a Docker Desktop zlyhávajú odlišne

Na linuxovom hostiteľovi sedia kontajnery na mostoch v mennom priestore hostiteľa. Všetko rozhoduje jedna tabuľka, takže uvedené porovnanie je celý príbeh: prečítajte trasu mosta, prečítajte trasu tunela a pozrite, ktorá vyhrá pre skutočnú adresu kontajnera.

Docker Desktop umiestňuje kontajnery za VM s vlastným NAT. Hostiteľ nemá k adrese kontajnera žiadnu trasu; k službe sa dostane cez publikovaný port, zvyčajne naviazaný na 127.0.0.1. Klient VPN preto môže službu pokaziť úplne bez prekryvu podsietí: buď nainštaluje trasu pre interný rozsah VM, alebo zablokuje loopbackovú prevádzku, kým je tunel pripojený. Ak ip route get na hostiteľovi hlási, že pre adresu kontajnera neexistuje trasa, je to očakávané a nie chyba.

Praktickým dôsledkom je, kam sa pozriete najskôr. Na Linuxe začnite smerovacou tabuľkou. Na Desktope začnite publikovaným portom a pravidlami firewallu klienta VPN a potom skontrolujte, či interná podsieť VM nekoliduje s niečím, čo tunel tlačí.

Overte so zapnutým tunelom

Pripojte VPN dvakrát, kým to vyhlásite za opravené, pretože profil, ktorý pri pripojení tlačí trasy a pri odpojení ich sťahuje, môže po prvom pokuse vyzerať správne. Potom spustite kontroly, ktoré klient skutočne vykonáva:

  1. ip route get z hostiteľa s použitím skutočnej adresy kontajnera.
  2. Požiadavka z iného kontajnera, aby sa dokázalo, že samotná služba je zdravá.
  3. curl -sv http://127.0.0.1:8080/ z klienta so zapnutým tunelom, potom traceroute -n na adresu kontajnera zo stroja v LAN.
  4. sysctl net.ipv4.conf.all.rp_filter, ak požiadavka dorazí na hostiteľa, ale odpoveď zmizne.

Nakoniec zapíšte zvolený rozsah do toho istého registra, z ktorého ste ho vybrali, s dátumom a projektom, ktorý ho vlastní. Ďalší prekryv príde z projektu, ktorý nikto nezdokumentoval, a jedinou obranou je, že rozsah bol rezervovaný zámerne, a nie vybraný náhodne.

Súvisiace články