Kako usmjeriti jednu aplikaciju kroz VPN bez cijele mašine
Nijedna neupravljana radna površina ne nudi VPN prekidač po procesu. Odaberite sloj koji bira saobraćaj: vezani socket, UID pravilo, profil firewall-a ili SOCKS skok.
VPN klijent se povezuje, preglednik radi, a ona jedna naredba koja vam je zaista važna i dalje izlazi kroz vašu kućnu vezu. Ili se dogodi suprotno: tunel preuzme zadanu rutu i lokalni datotečni server nestane s radne površine. Na to sam naišao s agentom za izgradnju koji je morao dosegnuti interni artefaktni mirror dok je ostatak hosta ostao na uredskom LAN-u, a klijent je nudio točno dvije opcije: sav saobraćaj ili ništa. Zahtjev je u oba smjera isti, ova aplikacija a ne cijela mašina, i većina klijenata nema kvačicu za to, jer tablica rutiranja nikada nije znala šta je aplikacija.
Zašto tablica rutiranja ne može vidjeti vašu aplikaciju
Kada proces pošalje paket, stek traži odredišnu adresu u tablici rutiranja. Ni ime izvršne datoteke ni port ne ulaze u to traženje. Domenska imena padaju iz istog razloga: tunel nosi saobraćaj do adrese, a dok se ime razriješi u adresu, rutiranje je jedina poluga koju jezgro još ima. Zato „VPN samo za ovu stranicu“ na kraju znači proxy, a „VPN samo za ovu aplikaciju“ znači jedan od malog skupa mehanizama.
| Mechanism | What selects | Covers | On tunnel drop |
|---|---|---|---|
| Socket bind | source address | a client you control | connections fail |
| UID rule (Linux) | owning user | every process of one account | connections fail |
| Firewall profile (Windows) | adapter profile | one program | fails closed |
| Network namespace | namespace membership | everything started inside | connections fail |
| SOCKS hop | app proxy setting | one app or one browser profile | connections fail |
Ništa od ovoga nije ruta po procesu. Svako premješta odluku na sloj koji vidi aplikaciju, korisnika ili vlastitu konfiguraciju aplikacije.
Jedno odredište je i dalje ruta, a ne pravilo aplikacije. Na macOS-u uobičajeni recept je skinuti kvačicu „Šalji sav saobraćaj preko VPN-a“ i dodati rutu do hosta: sudo route add -host internal-tuner.example -interface ppp0, koja se opet uklanja s sudo route delete -host internal-tuner.example -interface ppp0. Prvo pročitajte ime interfejsa iz ifconfig, jer je ppp0 samo primjer. Džokeri ne rade u ruti do hosta, pa usluga koja razgovara s nekoliko imena treba jedan zapis po imenu, a pravilo pokriva svaki proces na mašini, ne onaj koji ste imali na umu.
Vežite socket na adresu tunela
Kada kontrolirate klijent, vezivanje je najjeftiniji selektor. Socket vezan na lokalnu adresu tunela izlazi kroz taj interfejs sve dok tamo postoji ruta do odredišta, a sve ostalo na mašini zadržava svoj uobičajeni put. Suptilnost je u tome što vezivanje bira izvornu adresu dok tablica rutiranja još bira izlaz. Samo vezivanje ne premješta saobraćaj koji nema rutu u tunel, i upravo je to greška iza većine prijava „vezao sam ga a i dalje izlazi na pogrešnu stranu“.
import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))Alati višeg nivoa nude istu ideju: curl --interface 10.8.0.2, CURLOPT_INTERFACE u PHP-u i argument source_address u Python HTTP klijentima. Adresa mora pripadati tunelu, a greška u kucanju ovdje pada kao obična greška veze, ne kao pritužba na rutiranje. Vezivanje na ime uređaja umjesto na adresu je Linux privilegija i ne prenosi se na Windows ili macOS, zato prenosive skripte prosljeđuju adresu.
Linux: uparite vlasnika, ne ime aplikacije
Jezgro može upariti korisnika vlasnika socketa, pa posvećeni račun postaje selektor. Stavite tunel u vlastitu tablicu rutiranja i tamo pošaljite samo saobraćaj tog računa:
ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100Ovo radi samo ako tunel već nije zadana ruta. Pokrenite klijent s --route-nopull, ili filtrirajte gurnuti preusmjerivač s --pull-filter ignore "redirect-gateway" na OpenVPN 2.4 i novijem, pa sami dodajte zapis u tablicu. Inače postoje obje zadane rute i pobjeđuje ona s nižim prioritetom. Namjerna verzija toga je usmjeriti zadanu rutu na gateway tunela ili to učiniti iz skripte za odspajanje: drži saobraćaj van interneta kada tunel padne, ali to je prekidač, a ne selektor, i ostaje dok ga neko ne ukloni.
Jača verzija je mrežni namespace. Stvorite ga, pokrenite klijent unutra i pokrenite aplikaciju s ip netns exec. Ništa izvan namespacea ne vidi interfejs tunela, pa aplikacija ne može slučajno pasti natrag na rutu hosta. Cijena je stvarna: namespace treba veth par za dosezanje fizičke mreže i vlastitu datoteku resolvera, jer mount namespace ne dijeli postavke razrješavanja hosta.
Dva načina kvara objašnjavaju većinu curenja. Razrješavanje imena i dalje se događa u resolveru hosta, pa upit izlazi izvan tunela čak i kada TCP veza ulazi unutra. A IPv6 treba vlastito ip -6 rule, jer pravilo v4 ga ne pokriva.
Windows i macOS: ograničite firewall ili prepustite proxy
Windows također nema selektor rute po aplikaciji, ali njegova firewall pravila mogu se ograničiti na profil, a VPN adapter se može klasificirati kao „javni“ dok kućni LAN ostaje „privatni“. Napravite izlazna pravila blokiranja za program na profilima „privatni“ i „domen“, ostavite „javni“ otvoren, i aplikacija može dosegnuti mrežu samo kroz tunel. Prvo postavite mrežnu kategoriju veze, zatim potvrdite da se pravilo poklopilo u nadzornoj ploči firewall-a. To je blok, ne ruta: pada zatvoreno kada tunel padne i ne može zaustaviti aplikaciju koja ignorira firewall.
macOS slijedi istu logiku s drugim alatima. SOCKS slušalac dosegnut preko SSH-a najmanje je invazivna opcija, jer ssh -D 1080 user@host stvara jedan lokalni port i samo aplikacije konfigurirane da ga koriste idu tim putem. Pravilo pf može blokirati program po korisniku ili grupi, ali još ne može odabrati tunel samo za tu aplikaciju. Tunnelblick uopće ne može filtrirati po domeni, jer rute rade s adresama; korisnici OpenConnecta posežu za vpn-slice kada server gurne preširok popis prefiksa.
Dva zaobilazna rješenja pokrivaju ono što platformski alati promaše. Proširenja preglednika koja mijenjaju proxy po domeni praktičan su odgovor za „samo ova stranica“, jer djeluju na sloju aplikacije gdje imena još postoje; pokrivaju jedan preglednik i ništa drugo. Grubo rješenje je pokrenuti klijent dobavljača u virtualnoj mašini tako da gost posjeduje promjenu rute dok host zadržava svoj put, uz cijenu dva mrežna steka za održavanje.
SOCKS skok za alate bez opcije vezivanja
Većina aplikacija može se usmjeriti na HTTP ili SOCKS proxy čak i kada ne znaju ništa o interfejsima. SSH klijent nudi jedan bez promjene na strani servera:
ssh -N -D 127.0.0.1:9999 [email protected]Sve konfigurirano da koristi taj port izlazi na bastionu dok ostatak radne površine zadržava uobičajenu vezu. Lokalna instanca 3proxy vezana na adresu tunela radi isto za jedan port bez SSH-a, a stunnel pokriva jedan port umotan u TLS. Ograničenja su praktična: proxy nosi samo protokole koji ga znaju koristiti, UDP treba SOCKS5 UDP asocijaciju koju postavka „SOCKS5“ mnogih klijenata ne uključuje, a DNS se mora razriješiti kroz proxy (socks5h u curl-u), inače ime iscuri lokalnom resolveru.
Držite slušalac na loopbacku osim ako ga druga mašina treba.
Provjerite put snimkom, a ne statusnom porukom
Prozori statusa aplikacije opisuju postavku, ne paket. Snimite na oba interfejsa i uporedite:
tcpdump -i any -n port 443
ss -tnp | grep 443Ako se veza pojavi na fizičkom interfejsu bez odgovarajućeg zapisa na tunelu, selektor ne djeluje, šta god klijent izvijestio. Provjerite IPv6 i resolver odvojeno, i provjerite postoji li drugi put poput pomoćnog procesa ili naslijeđenog sistemskog proxyja.
Zatim odaberite granicu koja odgovara zahtjevu: proxy je dovoljan za jednu stranicu, UID pravilo je dovoljno za jedan račun, firewall profil je dovoljan kada veza mora pasti zatvoreno, a namespace je jedina opcija koja skriva tunel od svega izvan njega.