Kaip nukreipti pagrindinio kompiuterio srautą per Docker VPN konteinerį
VPN konteineris yra tinklo vardų erdvė, o ne tarpinis serveris. Pasirinkite bendrą netns, tikrą SOCKS klausytoją arba maršrutizuotą šliuzą, tada patikrinkite išėjimo kelią.
Jūsų tunelio konteineris veikia, docker compose exec vpn curl -s https://ifconfig.me atsako teikėjo adresu, o vis dėlto naršyklė jūsų darbalaukyje vis dar išeina per jūsų ISP. Šis atotrūkis yra numatomas. Konteineris, kuriame veikia VPN klientas, laiko tinklo vardų erdvę, maršrutus ir tunelio sąsają, o nieko, kas kalba HTTP ar SOCKS; paskelbus jame prievadą negalima sukurti klausytojo, kurio niekada nebuvo.
Tai, kur veikia klientas, lemia dizainą. Broliškas konteineris gali pereiti į tunelio vardų erdvę, darbalaukio programa negali, o maršrutizatoriui reikia maršrutų, o ne tarpinio serverio lauko. Suklydus dėl atitikmens, simptomas tas pats: atsisakyta jungtis arba srautas, kuris tyliai eina senu keliu.
Pritaikykite išdėstymą prie vietos, kur veikia klientas
Užduokite vieną klausimą prieš redaguodami Compose: ar klientą galima paleisti VPN konteinerio tinklo vardų erdvėje? Viskas, kas jau veikia kaip Linux konteineris, gali. Naršyklė, IDE ar CLI jūsų darbalaukyje negali, nes jos tarpinio serverio nuostata tikisi protokolo paslaugos, o ne vardų erdvės.
| Client | Arrangement | What must already exist |
|---|---|---|
| Another Compose service | Shares the vpn namespace via network_mode: service:vpn | A working tunnel and correct start order |
| Host browser, IDE or CLI | Proxy listener inside the namespace, published to host loopback | A configured SOCKS or HTTP proxy and its access rules |
| Router, VM or phone | The container as a layer-3 gateway | Forwarding, NAT and a return route |
Šie trys nesimaišo. HTTP tarpinio serverio laukas, nukreiptas į konteinerio tilto adresą, nieko nepasiekia, nebent ten klausosi tarpinis serveris, o tarpinio serverio klausytojas nenukreipia maršrutizatoriaus srauto. Pirmiausia nuspręskite, tada sekite atitinkamą skyrių.
Pasidalykite tunelio vardų erdve su brolišku konteineriu
Tai pigiausias variantas, nes nedalyvauja joks tarpinio serverio protokolas. Programa prisijungia prie vpn paslaugos vardų erdvės ir paveldi jos sąsajas, maršrutus ir prievadų erdvę:
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_healthyTrys apribojimai kyla iš to, kad vardų erdvė priklauso kitai paslaugai. Programa negauna savo networks rakto, nes neturi vardų erdvės, prie kurios prisitvirtinti. Prievadų skelbimas priklauso vpn, nes ten gyvena vardų erdvė. O iš naujo sukūrus vpn sunaikinama vardų erdvė, prie kurios prisijungė programa, todėl docker compose up -d --force-recreate vpn palieka jums iš naujo sukurti ir app; paprastas paleidimas iš naujo ne visada pakanka. Compose paslaugų nuoroda aprašo šį išdėstymą ir jo prievadų skelbimo apribojimą.
Nemanau, kad resolveris ateina kartu. /etc/resolv.conf yra failas kiekvienam konteineriui, o ne tinklo vardų erdvės dalis, todėl programa vis dar gali klausti pagrindinio kompiuterio resolverio, kol jos paketai išeina per tunelį. Perskaitykite jį konteinerio viduje ir nustatykite dns: programoje, kai privatūs vardai turi būti sprendžiami per tunelį.
docker compose exec app ip route
docker compose exec app cat /etc/resolv.conf
docker compose exec app curl -s https://ifconfig.meJei maršrutų sąraše yra tunelio sąsaja, o adresas yra teikėjo, programa yra tunelio viduje. Jei sąsajos nėra, app paleista prieš tai, kai vpn turėjo tunelį, todėl iš naujo sukurkite app, kai vpn praneš apie būklę.
Įdėkite tikrą tarpinio serverio klausytoją į vardų erdvę pagrindinio kompiuterio klientams
Darbalaukio naršyklė negali prisijungti prie vardų erdvės, todėl tunelis turi būti atskleistas kaip paslauga. Paleiskite tikrą SOCKS ar HTTP tarpinį serverį vpn vardų erdvėje ir paskelbkite tik jo prievadą:
services:
vpn:
ports:
- "127.0.0.1:1080:1080"
proxy:
image: your-proxy
network_mode: service:vpn
command: ["--socks", "0.0.0.0:1080"]Pagrindinio kompiuterio pusės adresas yra svarbioji to atitikmens pusė. 127.0.0.1:1080 kairėje laiko klausytoją už jūsų LAN; plikas "1080:1080" paskelbia atvirą tarpinį serverį kiekvienam įrenginiui, kuris gali pasiekti jūsų mašiną.
Konteinerio pusė turi savo spąstus. Paskelbti prievadai pristatomi į konteinerio adresą tilte, o ne į jo loopback, todėl tarpinis serveris, paleistas su --socks 127.0.0.1:1080 vardų erdvėje, priima brolių jungtis ir atmeta viską, kas ateina per paskelbtą prievadą. Pririškite jį prie 0.0.0.0 ir izoliacijai pasikliaukite pagrindinio kompiuterio pusės loopback susiejimu. Ta pati taisyklė galioja ir klausymosi adresui tarpinio serverio konfigūracijos faile.
Tada nuspręskite, kur sprendžiami vardai. curl atveju --socks5 išsprendžia pagrindinio kompiuterio vardą vietoje, o --socks5-hostname siunčia vardą tarpiniam serveriui; naršyklės rodo tą patį jungiklį kita etikete. Vietinis sprendimas nutekina užklausą net tada, kai puslapis įkeliamas per tunelį.
Laikykite konteinerį šliuzu tik su grįžimo maršrutu
Maršrutizatoriai, VM ir telefonai nenaudos HTTP tarpinio serverio lauko, o kai kurios programos visiškai nepaiso tarpinio serverio kintamųjų. Jų srauto maršrutizavimas reiškia 3 sluoksnį: konteineris persiunčia paketus ir verčia adresus tunelio sąsajoje.
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADEDu dalykus lengva praleisti. Klientui reikia maršruto, kuris jo numatytąjį šliuzą nukreiptų į šį pagrindinį kompiuterį, o atsakymai turi rasti kelią atgal, arba per statinį maršrutą viršutiniame maršrutizatoriuje, arba per NAT sąsajoje į klientus. Be vieno iš jų tunelis išneša užklausą lauk, o atsakymas dingsta.
Jis taip pat turi plačiausią poveikį. Pagrindinis kompiuteris, veikiantis kaip viso LAN šliuzas, siunčia kiekvieną neteisingai sukonfigūruotą klientą per jūsų VPN paskyrą, o tunelio kritimas arba užtemdys LAN, arba grįš prie ISP, priklausomai nuo kill switch.
Patikrinkite išėjimo kelią, tada grąžinkite atgal eilės tvarka
Tikrinkite šia tvarka ir sustokite prie pirmos klaidos: išėjimo adresas vardų erdvėje, išėjimo adresas iš pagrindinio kompiuterio per tarpinį serverį, tada vardų sprendimas privačiam pagrindiniam kompiuteriui.
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/healthPirmieji du adresai turi atitikti teikėją, o trečiasis turi būti išspręstas per tarpinį serverį, o ne nepavykti dėl vardo klaidos. Sutampanti pirmoji eilutė ir nepavykusi antroji reiškia, kad klausytojas arba paskelbtas prievadas yra neteisingas, o ne tunelis.
Grąžinimas atgal yra priešingybė sąrankai. Pašalinkite tarpinio serverio aplinkos kintamuosius iš shell profilio ir iš bet kurio systemd įrenginio, tada nuleiskite dėklą, kad bendra vardų erdvė išnyktų su savininku. Ištrinkite paskelbtą prievadą prieš ištrindami tarpinio serverio paslaugą, kitaip pagrindiniame kompiuteryje liks loopback klausytojas, kurio niekas neskaito.
Prieš judėdami toliau patvirtinkite keturis dalykus: jums svarbus klientas tikrai pasiekia tunelį, prievadus skelbia tik vardų erdvės savininkas, privatūs vardai sprendžiami ten, kur ketinote, ir niekas neklauso pagrindinio kompiuterio adrese, kuris nėra loopback. Kiekvienas jų tyliai nepavyksta produkcijoje, ir kiekvienas yra vienos eilutės patikra aukščiau.