VPN клијент се повеже, прегледач ради, а једина наредба која вас заиста занима и даље излази кроз вашу кућну везу. Или се догоди супротно: тунел преузме подразумевану руту и локални сервер датотека нестане са радне површине. То сам доживео са агентом за изградњу који је морао да достигне интерно огледало артефаката док је остатак хоста остао у канцеларијском LAN-у, а клијент је нудио тачно две могућности, сав саобраћај или ништа. Захтев је у оба смера исти, овај програм, а не цео рачунар, и већина клијената за њега нема поље за потврду, јер табела усмеравања никада није знала шта је програм.

Зашто табела усмеравања не види ваш програм

Када процес пошаље пакет, стек тражи одредишну адресу у табели усмеравања. Ни име извршне датотеке ни порт не улазе у то тражење. Називи домена падају из истог разлога: тунел преноси саобраћај на адресу, а када се назив разреши у адресу, усмеравање је једина полуга коју језгро још има. Зато "VPN само за овај сајт" на крају значи прокси, а "VPN само за овај програм" значи један од малог скупа механизама.

МеханизамШта бираПокриваКад тунел падне
Везивање сокетаизворна адресаклијент који контролишетевезе не успевају
UID правило (Linux)власнички корисниксваки процес једног налогавезе не успевају
Профил заштитног зида (Windows)профил адаптераједан програмпада у затвореном стању
Мрежни простор именачланство у простору именасве што се покрене унутравезе не успевају
SOCKS скокподешавање проксија у апликацијиједна апликација или један профил прегледачавезе не успевају

Ниједно од тога није рута по процесу. Свако премешта одлуку у слој који види програм, корисника или сопствену конфигурацију апликације.

Једно одредиште је и даље рута, а не правило за програм. На macOS-у је уобичајен рецепт искључити "Пошаљи сав саобраћај преко VPN-а" и додати руту до хоста: sudo route add -host internal-tuner.example -interface ppp0, која се затим уклања са sudo route delete -host internal-tuner.example -interface ppp0. Најпре прочитајте име интерфејса из ifconfig, јер је ppp0 само пример. Заменски знакови не раде у рути до хоста, па услуга која разговара с више назива треба један запис по називу, а правило покрива сваки процес на машини, не онај који сте имали на уму.

Вежите сокет на адресу тунела

Када контролишете клијент, везивање је најјефтинији бирач. Сокет везан на локалну адресу тунела излази кроз тај интерфејс док год тамо постоји рута до одредишта, а све остало на машини задржава свој уобичајени пут. Суптилност је у томе да везивање бира изворну адресу док излаз и даље бира табела усмеравања. Само везивање не премешта у тунел саобраћај који нема руту, и то је грешка за већином извештаја "везао сам га, а ипак излази погрешним путем".

import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))

Алати вишег нивоа нуде исту идеју: curl --interface 10.8.0.2, CURLOPT_INTERFACE у PHP-у и аргумент source_address у HTTP клијентима за Python. Адреса мора да припада тунелу, а грешка у куцању овде се показује као обична грешка везе, не као жалба на усмеравање. Везивање на име уређаја уместо на адресу привилегија је Linux-а и не преноси се на Windows или macOS, зато преносне скрипте прослеђују адресу.

Linux: спојите власника, а не име програма

Језгро може да упореди власничког корисника сокета, па наменски налог постаје бирач. Сместите тунел у сопствену табелу усмеравања и тамо шаљите само саобраћај тог налога:

ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100

То ради само ако тунел већ није подразумевана рута. Покрените клијент са --route-nopull или филтрирајте наметнуто преусмеравање помоћу --pull-filter ignore "redirect-gateway" на OpenVPN 2.4 и новијем, па сами додајте запис у табелу. Иначе постоје обе подразумеване руте и побеђује она нижег приоритета. Намерна верзија тога је усмерити подразумевану руту на гејтвеј тунела или то учинити из скрипте за одспајање: држи саобраћај ван интернета кад тунел падне, али то је прекидач за нужни прекид, не бирач, и остаје док га неко не уклони.

Јача верзија је мрежни простор имена. Направите га, покрените клијент унутра и покрените апликацију са ip netns exec. Ништа изван простора имена не види интерфејс тунела, па апликација не може случајно да се врати на руту хоста. Цена је стварна: простору имена треба veth пар за достизање физичке мреже и сопствена датотека резолвера, јер простор имена монтирања не дели подешавања разрешавања хоста.

Два начина квара објашњавају већину цурења. Разрешавање назива и даље се одвија у резолверу хоста, па упит излази изван тунела чак и кад TCP веза иде унутра. А IPv6 треба своје ip -6 rule, јер га правило v4 не покрива.

Windows и macOS: ограничите заштитни зид или предајте прокси

Ни Windows нема бирач руте по апликацији, али правила заштитног зида могу да се ограниче на профил, а VPN адаптер може да се класификује као јавни док кућни LAN остаје приватни. Направите правила блокирања одлазног саобраћаја за програм на профилима Приватно и Домен, оставите Јавно отворено, и апликација може да достигне мрежу само кроз тунел. Најпре подесите мрежну категорију везе, затим у надзорној табли заштитног зида потврдите да је правило погодило. То је блокада, не рута: пада у затвореном стању кад тунел падне и не може да заустави апликацију која игнорише заштитни зид.

macOS следи исту логику с другим алатима. SOCKS слушач достигнут преко SSH-а најмање је инвазивна опција, јер ssh -D 1080 user@host ствара један локални порт и тим путем иду само апликације подешене да га користе. Правило pf може да блокира програм по кориснику или групи, али и даље не може да изабере тунел само за тај програм. Tunnelblick уопште не може да филтрира по домену, јер руте раде с адресама; корисници OpenConnect-а посежу за vpn-slice кад сервер пошаље преширок списак префикса.

Две заобилазнице покривају оно што алати платформе промашују. Проширења прегледача која мењају прокси по домену практичан су одговор за "само овај сајт", јер делују на апликационом слоју где називи још постоје; покривају један прегледач и ништа друго. Груба је опција покренути клијент добављача у виртуелној машини, тако да гост поседује промену руте док хост задржава свој пут, уз цену два мрежна стека за одржавање.

SOCKS скок за алате без могућности везивања

Већина апликација може да се усмери на HTTP или SOCKS прокси чак и кад о интерфејсима не зна ништа. SSH клијент пружа га без промене на страни сервера:

ssh -N -D 127.0.0.1:9999 [email protected]

Све што је подешено да користи тај порт излази на бастиону док остатак радне површине задржава уобичајену везу. Локална инстанца 3proxy везана на адресу тунела чини исто за један порт без SSH-а, а stunnel покрива један порт умотан у TLS. Ограничења су практична: прокси преноси само протоколе који га знају користити, UDP тражи SOCKS5 UDP придруживање које подешавање "SOCKS5" многих клијената не омогућује, а DNS мора да разреши прокси (socks5h у curl-у) или назив процури до локалног резолвера.

Држите слушач на loopback-у осим ако га треба друга машина.

Проверите пут снимањем саобраћаја, а не статусном поруком

Статусни прозори апликације описују подешавање, не пакет. Снимите саобраћај на оба интерфејса и упоредите:

tcpdump -i any -n port 443
ss -tnp | grep 443

Ако се веза појави на физичком интерфејсу без одговарајућег записа на тунелу, бирач не делује, шта год клијент извештавао. Проверите одвојено IPv6 и резолвер, и потражите други пут, попут помоћног процеса или наслеђеног системског проксија.

Затим изаберите границу која одговара захтеву: прокси је довољан за један сајт, UID правило за један налог, профил заштитног зида кад веза мора да падне у затвореном стању, а простор имена једина је опција која крије тунел од свега изван њега.

Повезани чланци