VPN klients pieslēdzas, pārlūks strādā, un tā vienīgā komanda, kas jums tiešām rūp, joprojām iziet caur mājas savienojumu. Vai notiek pretējais: tunelis pārņem noklusējuma maršrutu, un vietējais failu serveris pazūd no darbvirsmas. Es ar to saskāros būvēšanas aģentā, kuram bija jāsasniedz iekšējs artefaktu spogulis, kamēr pārējā saimniekdatora daļa palika biroja LAN, un klients piedāvāja tieši divas izvēles: visa datplūsma vai nekas. Pieprasījums abos virzienos ir viens, šī programma, nevis visa mašīna, un lielākajai daļai klientu tam nav izvēles rūtiņas, jo maršrutu tabula nekad nav zinājusi, kas ir programma.

Kāpēc maršrutu tabula neredz jūsu programmu

Kad process sūta paketi, steks maršrutu tabulā meklē galamērķa adresi. Ne izpildāmās datnes nosaukums, ne ports šajā meklēšanā neietilpst. Domēnu nosaukumi neizdodas tā paša iemesla dēļ: tunelis pārvieto datplūsmu uz adresi, un, kad nosaukums ir atrisināts adresē, maršrutēšana ir vienīgā svira, kas kodolam vēl palikusi. Tāpēc «VPN tikai šai vietnei» galu galā nozīmē starpniekserveri, un «VPN tikai šai programmai» nozīmē vienu no neliela mehānismu kopuma.

MechanismWhat selectsCoversOn tunnel drop
Socket bindsource addressa client you controlconnections fail
UID rule (Linux)owning userevery process of one accountconnections fail
Firewall profile (Windows)adapter profileone programfails closed
Network namespacenamespace membershipeverything started insideconnections fail
SOCKS hopapp proxy settingone app or one browser profileconnections fail

Neviens no šiem nav maršruts katram procesam. Katrs pārvieto lēmumu uz slāni, kas redz programmu, lietotāju vai pašas lietotnes konfigurāciju.

Viens galamērķis joprojām ir maršruts, nevis programmas noteikums. macOS parastā recepte ir noņemt atzīmi «Sūtīt visu datplūsmu caur VPN» un pievienot saimniekdatora maršrutu: sudo route add -host internal-tuner.example -interface ppp0, kas atkal tiek noņemts ar sudo route delete -host internal-tuner.example -interface ppp0. Vispirms nolasiet saskarnes nosaukumu no ifconfig, jo ppp0 ir tikai piemērs. Aizstājējzīmes saimniekdatora maršrutā nestrādā, tāpēc pakalpojumam, kas runā ar vairākiem nosaukumiem, vajag vienu ierakstu katram nosaukumam, un noteikums attiecas uz katru mašīnas procesu, nevis to, kam bijāt domājis.

Piesaistiet ligzdu tuneļa adresei

Kad klientu kontrolējat jūs, piesaiste ir lētākais atlasītājs. Ligzda, kas piesaistīta tuneļa vietējai adresei, iziet caur šo saskarni, kamēr vien tur pastāv maršruts uz galamērķi, un viss pārējais mašīnā saglabā savu parasto ceļu. Smalkums ir tāds, ka piesaiste izvēlas avota adresi, kamēr maršrutu tabula joprojām izvēlas izeju. Piesaiste vien nepārvieto datplūsmu, kurai nav maršruta tunelī, un tieši šī kļūda ir aiz lielākās daļas ziņojumu «es to piesaistīju, un tas joprojām iziet nepareizajā pusē».

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

Augstāka līmeņa rīki piedāvā to pašu ideju: curl --interface 10.8.0.2, CURLOPT_INTERFACE PHP un source_address arguments Python HTTP klientos. Adresei jāpieder tunelim, un drukas kļūda šeit neizdodas kā parasta savienojuma kļūda, nevis kā maršrutēšanas sūdzība. Piesaiste ierīces nosaukumam adreses vietā ir Linux privilēģija un nepāriet uz Windows vai macOS, tāpēc pārnēsājamie skripti nodod adresi.

Linux: saskaņojiet īpašnieku, nevis programmas nosaukumu

Kodols var saskaņot ligzdas īpašnieku, tāpēc atsevišķs konts kļūst par atlasītāju. Ielieciet tuneli savā maršrutu tabulā un sūtiet tur tikai šī konta datplūsmu:

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

Tas darbojas tikai tad, ja tunelis jau nav noklusējuma maršruts. Palaidiet klientu ar --route-nopull, vai filtrējiet uzspiesto pāradresāciju ar --pull-filter ignore "redirect-gateway" OpenVPN 2.4 un jaunākās versijās, pēc tam paši pievienojiet tabulas ierakstu. Citādi pastāv abi noklusējumi, un uzvar tas, kuram ir zemāka prioritāte. Apzinātā tā versija ir vērst noklusējuma maršrutu uz tuneļa vārteju vai darīt to atvienošanas skriptā: tas notur datplūsmu ārpus interneta, kad tunelis krīt, bet tas ir izslēgšanas slēdzis, nevis atlasītājs, un tas paliek, līdz kāds to noņem.

Spēcīgākā versija ir tīkla nosaukumtelpa. Izveidojiet to, palaidiet klientu iekšpusē un palaidiet lietotni ar ip netns exec. Nekas ārpus nosaukumtelpas neredz tuneļa saskarni, tāpēc lietotne nevar nejauši atgriezties pie saimniekdatora maršruta. Izmaksas ir reālas: nosaukumtelpai vajag veth pāri, lai sasniegtu fizisko tīklu, un savu risinātāja datni, jo montāžas nosaukumtelpa nedala saimniekdatora izšķiršanas iestatījumus.

Divi kļūmes režīmi izskaidro lielāko daļu noplūžu. Nosaukumu izšķiršana joprojām notiek saimniekdatora risinātājā, tāpēc vaicājums iziet ārpus tuneļa arī tad, kad TCP savienojums iet iekšā. Un IPv6 vajag savu ip -6 rule, jo v4 noteikums to neaptver.

Windows un macOS: ierobežojiet ugunsmūri vai nododiet starpniekserveri

Arī Windows nav maršruta atlasītāja katrai lietotnei, bet tā ugunsmūra noteikumus var ierobežot ar profilu, un VPN adapteri var klasificēt kā «publisku», kamēr mājas LAN paliek «privāts». Izveidojiet izejošos bloķēšanas noteikumus programmai profilos «privāts» un «domēns», atstājiet «publisku» atvērtu, un lietotne tīklu sasniegs tikai caur tuneli. Vispirms iestatiet savienojuma tīkla kategoriju, pēc tam apstipriniet, ka noteikums sakrita ugunsmūra uzraudzības panelī. Tas ir bloķēšana, nevis maršruts: tas neizdodas slēgtā stāvoklī, kad tunelis krīt, un tas nevar apturēt lietotni, kas ignorē ugunsmūri.

macOS ievēro to pašu loģiku ar citiem rīkiem. SOCKS klausītājs, kas sasniedzams caur SSH, ir vismazāk invazīvā izvēle, jo ssh -D 1080 user@host izveido vienu vietējo portu, un tikai tam konfigurētas lietotnes iet šo ceļu. pf noteikums var bloķēt programmu pēc lietotāja vai grupas, bet tas joprojām nevar izvēlēties tuneli tikai šai programmai. Tunnelblick vispār nevar filtrēt pēc domēna, jo maršruti strādā ar adresēm; OpenConnect lietotāji ķeras pie vpn-slice, kad serveris uzspiež pārāk plašu prefiksu sarakstu.

Divi apiešanas ceļi nosedz to, ko platformas rīki palaiž garām. Pārlūka paplašinājumi, kas maina starpniekserveri pēc domēna, ir praktiskā atbilde uz «tikai šī vietne», jo tie darbojas lietotnes slānī, kur nosaukumi vēl pastāv; tie aptver vienu pārlūku un neko citu. Rupjais paņēmiens ir palaist piegādātāja klientu virtuālajā mašīnā, lai viesis pārvaldītu maršruta maiņu, kamēr saimnieks saglabā savu ceļu, par divu uzturamu tīkla steku cenu.

SOCKS lēciens rīkiem bez piesaistes iespējas

Lielāko daļu lietotņu var vērst uz HTTP vai SOCKS starpniekserveri pat tad, ja tās neko nezina par saskarnēm. SSH klients nodrošina vienu bez jebkādām izmaiņām servera pusē:

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

Viss, kas konfigurēts lietot šo portu, iziet pie bastiona, kamēr pārējā darbvirsma saglabā parasto savienojumu. Vietēja 3proxy instance, kas piesaistīta tuneļa adresei, dara to pašu vienam portam bez SSH, un stunnel aptver vienu TLS ietītu portu. Ierobežojumi ir praktiski: starpniekserveris pārvadā tikai tos protokolus, kas prot to lietot, UDP vajag SOCKS5 UDP asociāciju, ko daudzu klientu «SOCKS5» iestatījums neieslēdz, un DNS jāizšķir starpniekserverim (socks5h curl), citādi nosaukums noplūst vietējā risinātājā.

Turiet klausītāju uz loopback, ja vien tas nav vajadzīgs citai mašīnai.

Pārbaudiet ceļu ar uztveršanu, nevis statusa ziņojumu

Lietotnes statusa logi apraksta iestatījumu, nevis paketi. Uztveriet abās saskarnēs un salīdziniet:

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

Ja savienojums parādās fiziskajā saskarnē bez atbilstoša ieraksta tunelī, atlasītājs nav spēkā, lai ko klients ziņotu. Pārbaudiet IPv6 un risinātāju atsevišķi, un pārbaudiet, vai nav otra ceļa, piemēram, palīgprocess vai mantots sistēmas starpniekserveris.

Tad izvēlieties robežu, kas atbilst prasībai: vienai vietnei pietiek ar starpniekserveri, vienam kontam pietiek ar UID noteikumu, ugunsmūra profils pietiek, kad savienojumam jāneizdodas slēgtā stāvoklī, un nosaukumtelpa ir vienīgā iespēja, kas paslēpj tuneli no visa ārpus tā.

Saistītie raksti