Kiel sendi unu programon tra VPN sen la tuta maŝino
Neniu neadministrata labortablo ofertas VPN-ŝaltilon por unuopa procezo. Elektu la tavolon, kiu elektas trafikon: ligitan soketon, UID-regulon, fajroŝirmilan profilon aŭ SOCKS-salton.
La VPN-kliento konektiĝas, la retumilo funkcias, kaj la sola komando, pri kiu vi vere zorgas, ankoraŭ eliras tra via hejma konekto. Aŭ okazas la malo: la tunelo kaptas la defaŭltan itineron kaj la loka dosier-servilo malaperas de la labortablo. Mi trafis tion ĉe konstruagento, kiu devis atingi internan artefakt-spegulon dum la resto de la gastiganto restis en la oficeja LAN, kaj la kliento proponis precize du eblojn: la tuta trafiko aŭ nenio. La peto en ambaŭ direktoj estas la sama, ĉi tiu programo kaj ne la tuta maŝino, kaj la plej multaj klientoj havas neniun markobutonon por ĝi, ĉar la itinertabelo neniam sciis, kio estas programo.
Kial la itinertabelo ne povas vidi vian programon
Kiam procezo sendas paketon, la stako serĉas la celan adreson en la itinertabelo. Nek la nomo de la plenumebla dosiero nek la pordo eniras tiun serĉon. Domajnaj nomoj malsukcesas pro la sama kialo: tunelo portas trafikon al adreso, kaj kiam nomo solviĝas en unu, itinerigo estas la sola levilo, kiun la kerno ankoraŭ havas. Tial «VPN nur por ĉi tiu retejo» finfine signifas prokurilon, kaj «VPN nur por ĉi tiu programo» signifas unu el malgranda aro da mekanismoj.
| 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 |
Neniu el tiuj estas itinero por unuopa procezo. Ĉiu movas la decidon al tavolo, kiu vidas la programon, la uzanton aŭ la propran agordon de la aplikaĵo.
Unu sola celo ankoraŭ estas itinero, ne programregulo. Sur macOS la kutima recepto estas malŝalti «Sendi la tutan trafikon tra VPN» kaj aldoni gastigan itineron: sudo route add -host internal-tuner.example -interface ppp0, forigata denove per sudo route delete -host internal-tuner.example -interface ppp0. Unue legu la nomon de la interfaco el ifconfig, ĉar ppp0 estas nur ekzemplo. Sovaĝaj signoj ne funkcias en gastiga itinero, do servo, kiu parolas kun pluraj nomoj, bezonas unu enskribon por ĉiu nomo, kaj la regulo kovras ĉiun procezon sur la maŝino, ne tiun, kiun vi havis en la kapo.
Ligu la soketon al la adreso de la tunelo
Kiam vi regas la klienton, ligado estas la plej malmultekosta elektilo. Soketo ligita al la loka adreso de la tunelo eliras tra tiu interfaco tiel longe, kiel tie ekzistas itinero al la celo, kaj ĉio alia sur la maŝino konservas sian normalan vojon. La subtilaĵo estas, ke la ligado elektas la fontan adreson dum la itinertabelo ankoraŭ elektas la eliron. Ligado sola ne movas trafikon, kiu havas neniun itineron en la tunelon, kaj ĝuste tio estas la eraro malantaŭ la plej multaj raportoj «mi ligis ĝin kaj ĝi ankoraŭ iras la malĝustan vojon».
import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))Iloj de pli alta nivelo montras la saman ideon: curl --interface 10.8.0.2, CURLOPT_INTERFACE en PHP, kaj la argumento source_address en la HTTP-klientoj de Python. La adreso devas aparteni al la tunelo, kaj tajperaro ĉi tie malsukcesas kiel ordinara konekta eraro, ne kiel plendo pri itinerigo. Ligado al aparatnomo anstataŭ adreso estas privilegio de Linux kaj ne transiĝas al Windows aŭ macOS, tial porteblaj skriptoj transdonas la adreson.
Linux: kongruigu la posedanton, ne la programnomon
La kerno povas kongruigi la posedanton de soketo, do dediĉita konto fariĝas la elektilo. Metu la tunelon en sian propran itinertabelon kaj sendu tien nur la trafikon de tiu konto:
ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100Ĉi tio funkcias nur se la tunelo jam ne estas la defaŭlta itinero. Startigu la klienton per --route-nopull, aŭ filtru la puŝitan alidirektadon per --pull-filter ignore "redirect-gateway" ĉe OpenVPN 2.4 kaj pli nova, poste aldonu la tabelan enskribon mem. Alie ekzistas ambaŭ defaŭltoj kaj venkas tiu kun pli malalta prioritato. La intenca versio de tio estas direkti la defaŭltan itineron al la enirejo de la tunelo, aŭ fari tion el malkonekta skripto: ĝi tenas trafikon for de la interreto, kiam la tunelo falas, sed tio estas haltŝaltilo, ne elektilo, kaj ĝi restas ĝis iu forigos ĝin.
La pli forta versio estas reta nomspaco. Kreu ĝin, rulu la klienton interne, kaj startigu la aplikaĵon per ip netns exec. Nenio ekster la nomspaco vidas la tunelan interfacon, do la aplikaĵo ne povas hazarde refali al la gastiga itinero. La kosto estas reala: la nomspaco bezonas veth-paron por atingi la fizikan reton kaj sian propran solvilan dosieron, ĉar la muntada nomspaco ne dividas la solvajn agordojn de la gastiganto.
Du fiaskmanieroj klarigas la plej multajn likojn. Nomosolvado ankoraŭ okazas en la solvilo de la gastiganto, do la demando eliras ekster la tunelon eĉ kiam la TCP-konekto iras interne. Kaj IPv6 bezonas sian propran ip -6 rule, ĉar regulo v4 ne kovras ĝin.
Windows kaj macOS: limigu la fajroŝirmilon aŭ transdonu prokurilon
Ankaŭ Windows ne havas itineran elektilon por unuopa aplikaĵo, sed ĝiaj fajroŝirmilaj reguloj povas esti limigitaj al profilo, kaj VPN-adaptilo povas esti klasifikita kiel «publika» dum la hejma LAN restas «privata». Kreu elirajn blokajn regulojn por la programo en la profiloj «privata» kaj «domajna», lasu «publika» malfermita, kaj la aplikaĵo povas atingi la reton nur tra la tunelo. Unue agordu la retan kategorion de la konekto, poste konfirmu, ke la regulo kongruis en la monitora panelo de la fajroŝirmilo. Ĝi estas bloko, ne itinero: ĝi malsukcesas fermite, kiam la tunelo falas, kaj ĝi ne povas haltigi aplikaĵon, kiu ignoras la fajroŝirmilon.
macOS sekvas la saman logikon per aliaj iloj. SOCKS-auskultanto atingata per SSH estas la malplej invada opcio, ĉar ssh -D 1080 user@host kreas unu lokan pordon kaj nur aplikaĵoj agorditaj por uzi ĝin prenas tiun vojon. Regulo pf povas bloki programon laŭ uzanto aŭ grupo, sed ĝi ankoraŭ ne povas elekti la tunelon por tiu programo sole. Tunnelblick tute ne povas filtri laŭ domajno, ĉar itineroj laboras per adresoj; uzantoj de OpenConnect turniĝas al vpn-slice, kiam la servilo puŝas tro larĝan liston da prefiksoj.
Du ĉirkaŭvojoj kovras tion, kion la platformaj iloj maltrafas. Retumilaj etendaĵoj, kiuj ŝanĝas la prokurilon laŭ domajno, estas la praktika respondo al «nur ĉi tiu retejo», ĉar ili agas sur la aplikaĵa tavolo, kie nomoj ankoraŭ ekzistas; ili kovras unu retumilon kaj nenion alian. La kruda solvo estas ruli la klienton de la vendisto en virtuala maŝino, por ke la gasto posedu la itineran ŝanĝon dum la gastiganto konservas sian vojon, je la kosto de du retaj stakoj por prizorgi.
SOCKS-salto por iloj sen liga opcio
La plej multaj aplikaĵoj povas esti direktitaj al HTTP aŭ SOCKS-prokurilo eĉ kiam ili scias nenion pri interfacoj. SSH-kliento liveras unu sen ia ŝanĝo ĉe la servila flanko:
ssh -N -D 127.0.0.1:9999 [email protected]Ĉio agordita por uzi tiun pordon eliras ĉe la bastiono dum la resto de la labortablo konservas sian normalan konekton. Loka okazo de 3proxy ligita al la adreso de la tunelo faras la samon por unu pordo sen SSH, kaj stunnel kovras unu solan TLS-envolvitan pordon. La limoj estas praktikaj: prokurilo portas nur protokolojn, kiuj scias uzi ĝin, UDP bezonas SOCKS5 UDP-asocion, kiun la agordo «SOCKS5» de multaj klientoj ne ŝaltas, kaj DNS devas esti solvata de la prokurilo (socks5h en curl), alie la nomo likas al la loka solvilo.
Tenu la auskultanton sur loopback krom se alia maŝino bezonas ĝin.
Kontrolu la vojon per kapto, ne per statusa mesaĝo
Statusaj fenestroj de aplikaĵoj priskribas la agordon, ne la paketon. Kaptu sur ambaŭ interfacoj kaj komparu:
tcpdump -i any -n port 443
ss -tnp | grep 443Se la konekto aperas sur la fizika interfaco sen responda enskribo sur la tunelo, la elektilo ne efikas, kion ajn la kliento raportas. Kontrolu IPv6 kaj la solvilon aparte, kaj kontrolu ĉu ekzistas dua vojo, ekzemple helpa procezo aŭ heredita sistema prokurilo.
Poste elektu la limon, kiu kongruas kun la postulo: prokurilo sufiĉas por unu retejo, UID-regulo sufiĉas por unu konto, fajroŝirmila profilo sufiĉas, kiam la konekto devas malsukcesi fermite, kaj nomspaco estas la sola opcio, kiu kaŝas la tunelon de ĉio ekstere.