Váš kontejner tunelu funguje, docker compose exec vpn curl -s https://ifconfig.me odpovídá adresou poskytovatele, a přesto prohlížeč na vašem stole vychází přes vašeho ISP. Tato mezera je očekávaná. Kontejner, který spouští klienta VPN, drží síťový jmenný prostor, trasy a rozhraní tunelu, a nic, co mluví HTTP nebo SOCKS; publikování portu na něm nemůže vytvořit posluchač, který nikdy neexistoval.

Kde klient běží, rozhoduje o návrhu. Sourozenecký kontejner může přejít do jmenného prostoru tunelu, desktopová aplikace ne, a router potřebuje trasy, ne pole proxy. Spletete-li mapování, příznak je stejný: odmítnuté spojení nebo provoz, který tiše jde starou cestou.

Přizpůsobte uspořádání místu, kde klient běží

Položte jednu otázku, než upravíte Compose: lze klienta spustit uvnitř síťového jmenného prostoru kontejneru VPN? Cokoli, co už běží jako kontejner Linux, může. Prohlížeč, IDE nebo CLI na vašem stole nemohou, protože jeho nastavení proxy očekává protokolovou službu, ne jmenný prostor.

ClientArrangementWhat must already exist
Another Compose serviceShares the vpn namespace via network_mode: service:vpnA working tunnel and correct start order
Host browser, IDE or CLIProxy listener inside the namespace, published to host loopbackA configured SOCKS or HTTP proxy and its access rules
Router, VM or phoneThe container as a layer-3 gatewayForwarding, NAT and a return route

Tyto tři se nemíchají. Pole proxy HTTP namířené na mostovou adresu kontejneru nedosáhne ničeho, pokud tam proxy neposlouchá, a posluchač proxy nesměruje provoz routeru. Nejprve rozhodněte, pak následujte odpovídající oddíl.

Sdílejte jmenný prostor tunelu se sourozeneckým kontejnerem

Toto je nejlevnější možnost, protože se neúčastní žádný protokol proxy. Aplikace se připojí ke jmennému prostoru služby vpn a zdědí její rozhraní, trasy a prostor portů:

services:
  vpn:
    image: your-vpn-client
    cap_add:
      - NET_ADMIN
    healthcheck:
      test: ["CMD-SHELL", "ip link show tun0 >/dev/null"]
      interval: 10s
      retries: 5
  app:
    image: your-app
    network_mode: service:vpn
    depends_on:
      vpn:
        condition: service_healthy

Ze skutečnosti, že jmenný prostor patří jiné službě, plynou tři omezení. Aplikace nedostane vlastní klíč networks, protože nemá jmenný prostor, ke kterému by se připojila. Publikování portů patří vpn, protože tam jmenný prostor žije. A znovuvytvoření vpn zničí jmenný prostor, ke kterému se aplikace připojila, takže docker compose up -d --force-recreate vpn nechává na vás znovu vytvořit i app; prosté restartování ne vždy stačí. Reference služeb Compose pokrývá toto uspořádání a jeho omezení publikování portů.

Nepředpokládejte, že resolver přijde s ním. /etc/resolv.conf je soubor pro každý kontejner, ne součást síťového jmenného prostoru, takže aplikace stále může dotazovat resolver hostitele, zatímco její pakety odcházejí tunelem. Přečtěte jej uvnitř kontejneru a nastavte dns: na aplikaci, když se soukromá jména mají řešit tunelem.

docker compose exec app ip route
docker compose exec app cat /etc/resolv.conf
docker compose exec app curl -s https://ifconfig.me

Pokud seznam tras obsahuje rozhraní tunelu a adresa je poskytovatelova, aplikace je uvnitř tunelu. Pokud rozhraní chybí, app se spustil dřív, než vpn měl tunel, takže znovu vytvořte app, jakmile vpn ohlásí zdraví.

Umístěte skutečný posluchač proxy do jmenného prostoru pro klienty hostitele

Desktopový prohlížeč se nemůže připojit ke jmennému prostoru, takže tunel musí být vystaven jako služba. Spusťte skutečný proxy SOCKS nebo HTTP uvnitř jmenného prostoru vpn a publikujte jen jeho port:

services:
  vpn:
    ports:
      - "127.0.0.1:1080:1080"
  proxy:
    image: your-proxy
    network_mode: service:vpn
    command: ["--socks", "0.0.0.0:1080"]

Adresa na straně hostitele je důležitá polovina tohoto mapování. 127.0.0.1:1080 vlevo drží posluchač mimo vaši síť LAN; holé "1080:1080" publikuje otevřenou proxy každému zařízení, které dosáhne na váš stroj.

Strana kontejneru má vlastní past. Publikované porty se doručují na adresu kontejneru na mostě, ne na jeho loopback, takže proxy spuštěná s --socks 127.0.0.1:1080 uvnitř jmenného prostoru přijímá spojení od sourozenců a odmítá vše, co dorazí publikovaným portem. Připevněte ji k 0.0.0.0 a spolehněte se na navázání loopback na straně hostitele kvůli izolaci. Stejné pravidlo platí pro adresu naslouchání v konfiguračním souboru proxy.

Pak rozhodněte, kde se jména řeší. V curl --socks5 řeší jméno hostitele lokálně a --socks5-hostname posílá jméno proxy; prohlížeče vystavují stejný přepínač pod jiným označením. Lokální řešení prozradí dotaz, i když se stránka načítá tunelem.

Považujte kontejner za bránu jen se zpětnou trasou

Routery, VM a telefony nebudou používat pole proxy HTTP a některé aplikace proměnné proxy úplně ignorují. Směrovat jejich provoz znamená vrstvu 3: kontejner předává pakety a překládá adresy na rozhraní tunelu.

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

Dvě věci se snadno přehlédnou. Klient potřebuje trasu, která jeho výchozí bránu nasměruje na tohoto hostitele, a odpovědi si musí najít cestu zpět, buď statickou trasou na nadřazeném routeru, nebo NAT na rozhraní obráceném ke klientům. Bez jednoho z toho tunel vynese požadavek ven a odpověď zmizí.

Má také nejširší dosah. Hostitel v roli brány pro celou síť LAN pošle každého špatně nastaveného klienta přes váš účet VPN a výpadek tunelu buď zablokuje LAN, nebo se vrátí k ISP podle kill switch.

Ověřte cestu odchodu a pak se vracejte v pořadí

Kontrolujte v tomto pořadí a zastavte se u prvního selhání: odchozí adresa uvnitř jmenného prostoru, odchozí adresa z hostitele přes proxy, potom řešení jmen pro soukromý hostitel.

docker compose exec vpn curl -s https://ifconfig.me
curl -s -x socks5h://127.0.0.1:1080 https://ifconfig.me
curl -s -x socks5h://127.0.0.1:1080 http://internal.example/health

První dvě adresy mají odpovídat poskytovateli a třetí se má vyřešit přes proxy, místo aby selhala s chybou jména. Shoda prvního řádku a selhání druhého znamená, že špatný je posluchač nebo publikovaný port, ne tunel.

Vrácení je opak nastavení. Odstraňte proměnné prostředí proxy z profilu shellu a z jakékoli jednotky systemd, pak spusťte stack dolů, aby sdílený jmenný prostor zmizel se svým vlastníkem. Smažte publikovaný port před smazáním služby proxy, jinak hostiteli zůstane posluchač loopback, který nikdo nečte.

Než půjdete dál, potvrďte čtyři věci: klient, na kterém vám záleží, skutečně dosáhne tunelu, porty publikuje jen vlastník jmenného prostoru, soukromá jména se řeší tam, kde jste chtěli, a nic neposlouchá na adrese hostitele, která není loopback. Každá z nich v produkci tiše selhává a každá je kontrolou na jeden řádek výše.

Související články