Вашиот контејнер за тунел работи, docker compose exec vpn curl -s https://ifconfig.me одговара со адресата на давателот, а сепак прелистувачот на вашата работна површина сѐ уште излегува преку вашиот ISP. Овој јаз е очекуван. Контејнерот што извршува VPN клиент држи мрежен именски простор, рути и интерфејс на тунел, и ништо што зборува HTTP или SOCKS; објавувањето порта на него не може да создаде слушател што никогаш не постоел.

Каде работи клиентот го одредува дизајнот. Братен контејнер може да се пресели во именскиот простор на тунелот, десктоп апликацијата не може, а рутерот бара рути, а не поле за прокси. Ако погрешите со мапирањето, симптомот е ист: одбиена врска или трафик што тивко оди по стариот пат.

Прилагодете го распоредот на местото каде работи клиентот

Поставете едно прашање пред да го уредите Compose: може ли клиентот да се стартува во мрежниот именски простор на VPN контејнерот? Сѐ што веќе работи како Linux контејнер може. Прелистувач, IDE или CLI на вашата маса не може, бидејќи неговото поставување за прокси очекува протоколна услуга, а не именски простор.

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

Овие три не се мешаат. Поле за HTTP прокси насочено кон мостната адреса на контејнерот не достигнува ништо ако таму не слуша прокси, а слушателот на прокси не го насочува трафикот на рутерот. Прво одлучете, потоа следете го соодветниот дел.

Споделете го именскиот простор на тунелот со братен контејнер

Ова е најевтината опција бидејќи не е вклучен протокол за прокси. Апликацијата се приклучува на именскиот простор на услугата vpn и ги наследува нејзините интерфејси, рути и простор за порти:

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

Три ограничувања произлегуваат од тоа што именскиот простор и припаѓа на друга услуга. Апликацијата не добива сопствен клуч networks, бидејќи нема именски простор на кој би се прикачила. Објавувањето порти и припаѓа на vpn, бидејќи таму живее именскиот простор. А пресоздавањето на vpn го уништува именскиот простор на кој се приклучила апликацијата, затоа docker compose up -d --force-recreate vpn ве остава да ја пресоздадете и app; обичен рестарт не е секогаш доволен. Референцата за Compose услуги го покрива овој распоред и неговото ограничување за објавување порти.

Не претпоставувајте дека резолверот доаѓа со него. /etc/resolv.conf е датотека по контејнер, а не дел од мрежниот именски простор, затоа апликацијата сѐ уште може да го праша резолверот на домаќинот додека нејзините пакети излегуваат низ тунелот. Прочитајте ја внатре во контејнерот и поставете dns: на апликацијата кога приватните имиња треба да се решат низ тунелот.

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

Ако списокот со рути го содржи интерфејсот на тунелот и адресата е на давателот, апликацијата е внатре во тунелот. Ако интерфејсот недостасува, app стартувала пред vpn да има тунел, затоа пресоздадете app штом vpn пријави здравје.

Поставете вистински слушател на прокси во именскиот простор за клиентите на домаќинот

Десктоп прелистувачот не може да се приклучи на именски простор, затоа тунелот мора да се изложи како услуга. Стартувајте вистински SOCKS или HTTP прокси внатре во именскиот простор vpn и објавете само неговата порта:

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

Адресата од страната на домаќинот е важната половина од тоа мапирање. 127.0.0.1:1080 лево го држи слушателот надвор од вашата LAN; голо "1080:1080" објавува отворено прокси на секој уред што може да стигне до вашата машина.

Страната на контејнерот има сопствена стапица. Објавените порти се доставуваат до адресата на контејнерот на мостот, а не до неговиот loopback, затоа прокси стартувано со --socks 127.0.0.1:1080 внатре во именскиот простор прифаќа врски од браќата и одбива сѐ што пристигнува низ објавената порта. Врзете го за 0.0.0.0 и за изолација сметајте на loopback врската од страната на домаќинот. Истото правило важи и за адресата за слушање во конфигурациската датотека на проксито.

Потоа одлучете каде се решаваат имињата. Во curl, --socks5 го решава името на домаќинот локално, а --socks5-hostname го праќа името до проксито; прелистувачите го изложуваат истиот прекинувач под друга ознака. Локалното решавање го изнесува барањето дури и кога страницата се вчитува низ тунелот.

Третирајте го контејнерот како порта само со повратна рута

Рутерите, VM и телефоните нема да користат поле за HTTP прокси, а некои апликации целосно ги игнорираат променливите за прокси. Насочувањето на нивниот трафик значи слој 3: контејнерот проследува пакети и преведува адреси на интерфејсот на тунелот.

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

Две работи лесно се пропуштаат. На клиентот му треба рута што ја насочува неговата стандардна порта кон овој домаќин, а одговорите мора да го најдат патот назад, или преку статична рута на горниот рутер или преку NAT на интерфејсот кон клиентите. Без едно од двете, тунелот го изнесува барањето надвор и одговорот исчезнува.

Има и најширок радиус на влијание. Домаќин што служи како порта за целата LAN го праќа секој погрешно конфигуриран клиент низ вашата VPN сметка, а падот на тунелот или ја затемнува LAN или се враќа на ISP во зависност од kill switch.

Проверете ја излезната патека, потоа вратете се по ред

Проверете по овој ред и застанете при првиот неуспех: излезна адреса во именскиот простор, излезна адреса од домаќинот преку проксито, потоа решавање на имиња за приватен домаќин.

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

Првите две адреси треба да се совпаѓаат со давателот, а третата треба да се реши преку проксито наместо да пропадне со грешка за име. Совпаѓање на првата линија и неуспех на втората значи дека слушателот или објавената порта е погрешен, а не тунелот.

Враќањето е спротивно од поставувањето. Отстранете ги променливите на околината за прокси од профилот на школката и од секоја systemd единица, потоа спуштете го стекот за да исчезне заедничкиот именски простор со неговиот сопственик. Избришете ја објавената порта пред да ја избришете прокси услугата, инаку домаќинот задржува loopback слушател што никој не го чита.

Пред да продолжите, потврдете четири работи: клиентот што ве интересира навистина стигнува до тунелот, портите ги објавува само сопственикот на именскиот простор, приватните имиња се решаваат таму каде што сте сакале, и ништо не слуша на адреса на домаќин што не е loopback. Секое од нив тивко пропаѓа во производство, и секое е проверка од една линија погоре.

Поврзани статии