Vaš vsebnik tunela deluje, docker compose exec vpn curl -s https://ifconfig.me odgovarja z naslovom ponudnika, in vendar brskalnik na vaši delovni površini še vedno izhaja prek vašega ISP. Ta vrzel je pričakovana. Vsebnik, ki izvaja odjemalca VPN, drži imenski prostor omrežja, poti in vmesnik tunela, in nič, kar govori HTTP ali SOCKS; objava vrat na njem ne more ustvariti poslušalca, ki ga ni nikoli bilo.

Kje se odjemalec izvaja, odloča o zasnovi. Sosednji vsebnik lahko preide v imenski prostor tunela, namizna aplikacija ne more, usmerjevalnik pa potrebuje poti, ne polja posrednika. Če zamešate preslikavo, je simptom enak: povezava zavrnjena ali promet, ki tiho ubere staro pot.

Prilagodite ureditev kraju, kjer se odjemalec izvaja

Postavite eno vprašanje, preden uredite Compose: je mogoče odjemalca zagnati znotraj imenskega prostora omrežja vsebnika VPN? Vse, kar že teče kot vsebnik Linux, lahko. Brskalnik, IDE ali CLI na vaši mizi ne more, ker njegova nastavitev posrednika pričakuje protokolarno storitev, ne imenskega prostora.

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

Ti trije se ne mešajo. Polje posrednika HTTP, usmerjeno na mostni naslov vsebnika, ne doseže ničesar, če tam ne posluša posrednik, poslušalec posrednika pa ne usmerja prometa usmerjevalnika. Najprej se odločite, nato sledite ustreznemu razdelku.

Delite imenski prostor tunela s sosednjim vsebnikom

To je najcenejša možnost, ker ni vključen noben protokol posrednika. Aplikacija vstopi v imenski prostor storitve vpn in podeduje njene vmesnike, poti in prostor vrat:

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

Iz dejstva, da imenski prostor pripada drugi storitvi, izhajajo tri omejitve. Aplikacija ne dobi lastnega ključa networks, ker nima imenskega prostora, na katerega bi se pripela. Objavljanje vrat pripada vpn, saj tam živi imenski prostor. In ponovno ustvarjanje vpn uniči imenski prostor, v katerega je vstopila aplikacija, zato docker compose up -d --force-recreate vpn prepušča vam, da znova ustvarite tudi app; navaden ponovni zagon ni vedno dovolj. Referenca storitev Compose pokriva to ureditev in njeno omejitev objavljanja vrat.

Ne predpostavljajte, da razreševalnik pride zraven. /etc/resolv.conf je datoteka na vsebnik, ne del imenskega prostora omrežja, zato lahko aplikacija še vedno vpraša razreševalnik gostitelja, medtem ko njena paketa odhajata skozi tunel. Preberite jo znotraj vsebnika in nastavite dns: na aplikaciji, ko je treba zasebna imena razrešiti skozi tunel.

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

Če seznam poti vsebuje vmesnik tunela in je naslov ponudnikov, je aplikacija znotraj tunela. Če vmesnika ni, se je app zagnala, preden je vpn imel tunel, zato znova ustvarite app, ko vpn poroča o zdravju.

V imenski prostor postavite pravega poslušalca posrednika za odjemalce gostitelja

Namizni brskalnik ne more vstopiti v imenski prostor, zato je treba tunel izpostaviti kot storitev. Zaženite pravi posrednik SOCKS ali HTTP znotraj imenskega prostora vpn in objavite samo njegova vrata:

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

Naslov na strani gostitelja je pomembna polovica te preslikave. 127.0.0.1:1080 na levi drži poslušalca zunaj vaše LAN; goli "1080:1080" objavi odprt posrednik vsaki napravi, ki lahko doseže vaš stroj.

Stran vsebnika ima svojo past. Objavljena vrata se dostavijo na naslov vsebnika na mostu, ne na njegov loopback, zato posrednik, zagnan z --socks 127.0.0.1:1080 v imenskem prostoru, sprejema povezave sosedov in zavrača vse, kar pride skozi objavljena vrata. Privežite ga na 0.0.0.0 in se za izolacijo zanesite na vezavo loopback na strani gostitelja. Isto pravilo velja za naslov poslušanja v konfiguracijski datoteki posrednika.

Nato odločite, kje se imena razrešujejo. V curl --socks5 razreši ime gostitelja lokalno, --socks5-hostname pa pošlje ime posredniku; brskalniki ponujajo isto stikalo pod drugo oznako. Lokalno razreševanje razkrije poizvedbo, tudi ko se stran naloži skozi tunel.

Obravnavajte vsebnik kot prehod samo s povratno potjo

Usmerjevalniki, VM in telefoni ne bodo uporabili polja posrednika HTTP, nekatere aplikacije pa spremenljivke posrednika povsem ignorirajo. Usmerjanje njihovega prometa pomeni plast 3: vsebnik posreduje pakete in prevaja naslove na vmesniku tunela.

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

Dve stvari zlahka spregledate. Odjemalec potrebuje pot, ki njegova privzeta vrata usmeri na tega gostitelja, odgovori pa morajo najti pot nazaj, bodisi po statični poti na nadrejenem usmerjevalniku bodisi po NAT na vmesniku proti odjemalcem. Brez enega od tega tunel odnese zahtevo ven in odgovor izgine.

Ima tudi najširši doseg. Gostitelj kot prehod za celotno LAN pošlje vsakega napačno nastavljenega odjemalca skozi vaš račun VPN, padec tunela pa bodisi zatemni LAN bodisi se vrne na ISP glede na kill switch.

Preverite izhodno pot in nato zavrtite nazaj po vrstnem redu

Preverjajte v tem vrstnem redu in se ustavite ob prvi napaki: izhodni naslov v imenskem prostoru, izhodni naslov z gostitelja skozi posrednika, nato razreševanje imen za zasebnega gostitelja.

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

Prva dva naslova se morata ujemati s ponudnikom, tretji pa se mora razrešiti skozi posrednika, namesto da bi spodletel z napako imena. Ujemajoča se prva vrstica in spodletela druga pomenita, da so napačna poslušalec ali objavljena vrata, ne tunel.

Vračanje nazaj je nasprotje nastavitve. Odstranite okoljske spremenljivke posrednika iz profila lupine in iz katere koli enote systemd, nato spustite sklad, da skupni imenski prostor izgine s svojim lastnikom. Izbrišite objavljena vrata, preden izbrišete storitev posrednika, sicer gostitelju ostane poslušalec loopback, ki ga nihče ne bere.

Preden nadaljujete, potrdite štiri stvari: odjemalec, ki vam je pomemben, res doseže tunel, vrata objavlja samo lastnik imenskega prostora, zasebna imena se razrešujejo tam, kjer ste nameravali, in nič ne posluša na naslovu gostitelja, ki ni loopback. Vsaka od teh v produkciji tiho spodleti in vsaka je preverjanje v eni vrstici zgoraj.

Sorodni članki