Kontejner Docker nedostupný přes VPN? Porovnejte podsítě
Docker přiděluje podsíť, kterou si nárokuje i VPN. Porovnejte oba plány adres a vyberte opravu, která přežije opětovné připojení.
Kontejnery odpovídají v kancelářské LAN a přestanou odpovídat ve chvíli, kdy se připojí firemní VPN. V kontejneru se nic nezměnilo: žádný restart, žádná aktualizace image, žádná úprava konfigurace. Změnila se směrovací tabulka hostitele, kde trasa, kterou tunel přidal, nyní pokrývá adresu, kterou Docker přidělil. Než upravíte podsíť nebo požádáte o výjimku z VPN, položte oba plány adres vedle sebe, protože opravy stojí velmi rozdílné množství času.
Přečtěte trasu, než změníte konfiguraci
Začněte sítí, kterou Docker skutečně postavil. Blok IPAM je plán adres a podsíť je řádek, na kterém záleží:
docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]Compose ve výchozím nastavení přiděluje každému novému projektu /16, takže dvě služby se mohou vejít do rozsahu 65,536 adres. Právě tato šířka je důvod, proč jsou překryvy běžné: náhodně vybraná /16 je dost velká na to, aby pohltila lokalitu, kterou dosahujete tunelem, a nikdo si toho nevšimne, dokud se tunel nezvedne.
Poté porovnejte výběr trasy pro jednu adresu kontejneru, jednou s vypnutým tunelem a jednou se zapnutým:
ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1Dva tvary odpovědi vedou na různá místa. Pokud výstup uvádí tun0, wg0 nebo jiné tunelové zařízení, je prefix VPN přinejmenším stejně specifický jako trasa mostu a paket se nikdy nedostane ke kontejneru. Pokud stále uvádí most, hostitel se ke kontejneru dostane a vaše závada je filtrování, DNS nebo zpětná cesta, která selhává jen v jednom směru.
Proč je kolize /16 snadno dosažitelná
Docker bere mostové sítě z privátních fondů a výchozí fond vychází z bloku 172.16.0.0/12 po řezech /16. Firemní sítě často používají stejný privátní prostor a VPN pro vzdálený přístup tlačí tyto prefixy na každého připojeného klienta. Když obě strany věří, že vlastní 172.18.0.0/16, jedna směrovací tabulka drží dvě protichůdná tvrzení.
O vítězi rozhoduje délka prefixu, ne pořadí, v jakém se trasy objeví. Tunel, který tlačí 10.0.0.0/8 nepřekoná trasu mostu 172.18.0.0/16, protože /8 je méně specifický. Tunel, který tlačí 172.18.0.0/16, nebo 172.18.5.0/24 uvnitř něj, ano. Proto jeden notebook funguje v kancelářské síti a selhává na hotelovém Wi-Fi se stejnou VPN: klient dostává různé prefixy.
Stejná tabulka řídí i opačný směr. Kontejner, který potřebuje interního hostitele na 10.8.4.20 pošle paket na svou mostovou bránu a hostitel ho pak směruje do tunelu. Tato cesta obvykle funguje, protože hostitel provádí NAT, ale selhává, když firemní strana přijímá jen VPN adresu notebooku, nebo když filtrování zpětné cesty zahodí asymetrickou odpověď.
Porovnejte tři opravy
Existují jen tři východiska a liší se v tom, kdo je musí schválit a co se rozbije, když jedno aplikujete.
| 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 |
Přečíslování je jediná oprava, kterou zvládnete bez tiketu, a proto většina návodů končí tam. Je levná u mladého projektu a drahá, jakmile nástroj pro migraci nebo uložený připojovací řetězec ukazuje na doslovnou adresu. Spočítejte tyto odkazy před úpravou YAML, ne po ní.
Výjimka z tunelu je nejčistší odpověď, když překryv leží v rozsahu, který vaše firma skutečně vlastní. Je také nejpomalejší a je k ničemu pro dodavatele, který nemůže změnit profil klienta. Publikovaný port nebo malý reverzní proxy se hádce vyhnou: klient mluví s adresou, kterou tunel už správně směruje, a dostupný musí být jen tento port.
Zafixujte rozsah záměrně
U jednoho projektu deklarujte podsíť v souboru compose, aby projekt přestal čerpat ze sdíleného fondu:
networks:
default:
ipam:
config:
- subnet: 10.201.7.0/24Vezměte tento rozsah z registru, který vede váš tým, ne z příkladu nalezeného při hledání. Zkontrolujte ho proti prefixům, které VPN tlačí, domácím LAN, ze kterých lidé pracují, a dalším kontejnerovým sítím na stejném hostiteli. Pak naplánujte znovuvytvoření, protože existující síť si ponechává starou podsíť: docker compose down, poté up -d. docker network rm odmítá, dokud jsou připojené koncové body, a každý ipv4_address záznam v souboru musí spadnout do nového rozsahu.
Pro sítě, které Docker vytváří 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 platí pro sítě vytvořené po restartu démona a mosty, které už existují, si ponechávají své adresy. To je pohodlné a snadno zapomenutelné, takže považujte starý projekt za stále se překrývající, dokud někdo jeho síť znovu nevytvoří. Dokumentace Dockeru k sítím enginu popisuje pravidla přidělování, pokud potřebujete fond obhájit při revizi.
Most Linuxu a Docker Desktop selhávají jinak
Na hostiteli Linuxu sedí kontejnery na mostech v jmenném prostoru hostitele. O všem rozhoduje jedna tabulka, takže výše uvedené srovnání je celý příběh: přečtěte trasu mostu, přečtěte trasu tunelu a podívejte se, která vyhraje pro skutečnou adresu kontejneru.
Docker Desktop staví kontejnery za VM s vlastním NAT. Hostitel nemá k adrese kontejneru vůbec žádnou trasu; ke službě se dostane přes publikovaný port, obvykle svázaný s 127.0.0.1. Klient VPN tedy může službu rozbít i bez jakéhokoli překryvu podsítí, buď instalací trasy pro interní rozsah VM, nebo blokováním provozu loopback, dokud je tunel připojený. Pokud ip route get na hostiteli hlásí, že pro adresu kontejneru není trasa, je to očekávané, a ne závada.
Praktickým důsledkem je, kam se díváte nejdřív. Na Linuxu začněte u směrovací tabulky. Na Desktopu začněte u publikovaného portu a pravidel firewallu klienta VPN, potom zkontrolujte, zda se interní podsíť VM nesráží s něčím, co tunel tlačí.
Ověřte se zapnutým tunelem
Připojte VPN dvakrát, než to prohlásíte za opravené, protože profil, který při připojení tlačí trasy a při odpojení je stahuje, může po prvním pokusu vypadat správně. Potom spusťte kontroly, které klient skutečně spouští:
ip route getz hostitele s použitím skutečné adresy kontejneru.- Požadavek z jiného kontejneru, abyste dokázali, že samotná služba je zdravá.
curl -sv http://127.0.0.1:8080/z klienta se zapnutým tunelem, potétraceroute -nna adresu kontejneru ze stroje v LAN.sysctl net.ipv4.conf.all.rp_filterpokud požadavek dorazí na hostitele, ale odpověď zmizí.
Nakonec zapište zvolený rozsah do stejného registru, ze kterého jste ho vzali, s datem a projektem, kterému patří. Další překryv přijde z projektu, který nikdo nedokumentoval, a jedinou obranou je, že rozsah byl rezervován záměrně, a ne vytažen náhodně.