Yhden sovelluksen reitittäminen VPN:n läpi ilman koko konetta
Mikään hallitsematon työpöytä ei tarjoa prosessikohtaista VPN-kytkintä. Valitse kerros, joka valitsee liikenteen: sidottu socket, UID-sääntö, palomuuriprofiili tai SOCKS-hyppy.
VPN-asiakas yhdistää, selain toimii, ja se ainoa komento, josta todella välität, lähtee yhä kotiyhteytesi kautta. Tai käy päinvastoin: tunneli ottaa oletusreitin ja paikallinen tiedostopalvelin katoaa työpöydältä. Törmäsin tähän build-agentissa, jonka piti tavoittaa sisäinen artefaktien peili, kun muu isäntä jäi toimiston lähiverkkoon, ja asiakas tarjosi täsmälleen kaksi vaihtoehtoa: kaikki liikenne tai ei mitään. Pyyntö on molempiin suuntiin sama, tämä ohjelma eikä koko kone, ja useimmilla asiakkaille ei ole siihen valintaruutua, koska reititystaulu ei ole koskaan tiennyt, mikä ohjelma on.
Miksi reititystaulu ei näe ohjelmaasi
Kun prosessi lähettää paketin, pino etsii kohdeosoitteen reititystaulusta. Eivät suoritettavan tiedoston nimi eikä portti tule siihen hakuun. Verkkotunnukset epäonnistuvat samasta syystä: tunneli kuljettaa liikennettä osoitteeseen, ja kun nimi on ratkennut osoitteeksi, reititys on ainoa vipu, joka ytimellä vielä on. Siksi „VPN vain tälle sivustolle“ tarkoittaa lopulta välityspalvelinta ja „VPN vain tälle ohjelmalle“ yhtä pientä mekanismijoukkoa.
| 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 |
Mikään näistä ei ole prosessikohtainen reitti. Jokainen siirtää päätöksen kerrokseen, joka näkee ohjelman, käyttäjän tai sovelluksen oman kokoonpanon.
Yksi kohde on yhä reitti, ei ohjelmasääntö. macOS:ssa tavallinen resepti on poistaa valinta „Lähetä kaikki liikenne VPN:n kautta“ ja lisätä isäntäreitti: sudo route add -host internal-tuner.example -interface ppp0, joka poistetaan jälleen komennolla sudo route delete -host internal-tuner.example -interface ppp0. Lue ensin liitännäisen nimi komennon ifconfig tulosteesta, sillä ppp0 on vain esimerkki. Jokerimerkit eivät toimi isäntäreitissä, joten usean nimen kanssa puhuva palvelu tarvitsee yhden merkinnän kutakin nimeä kohden, ja sääntö kattaa jokaisen koneen prosessin, ei sitä, jota ajattelit.
Sido socket tunnelin osoitteeseen
Kun hallitset asiakasta, sidonta on halvin valitsin. Tunnelin paikalliseen osoitteeseen sidottu socket lähtee tuon liitännäisen kautta niin kauan kuin sinne on reitti kohteeseen, ja kaikki muu koneessa säilyttää tavallisen polkunsa. Hienous on siinä, että sidonta valitsee lähdeosoitteen, kun taas reititystaulu valitsee edelleen ulostulon. Pelkkä sidonta ei siirrä liikennettä, jolla ei ole reittiä tunneliin, ja juuri se virhe on useimpien „sidon sen enkä silti mene oikeaan suuntaan“ -raporttien takana.
import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))Korkeamman tason työkalut tarjoavat saman idean: curl --interface 10.8.0.2, PHP:n CURLOPT_INTERFACE ja Pythonin HTTP-asiakkaiden source_address-argumentti. Osoitteen on kuuluttava tunnelille, ja kirjoitusvirhe täällä epäonnistuu tavallisena yhteysvirheenä, ei reititysvalituksena. Laitteen nimeen sitominen osoitteen sijaan on Linuxin etuoikeus eikä siirry Windowsiin tai macOS:ään, siksi siirrettävät skriptit välittävät osoitteen.
Linux: sovita omistaja, älä ohjelman nimeä
Ydin voi sovittaa socketin omistavan käyttäjän, joten omistettu tili tulee valitsimeksi. Laita tunneli omaan reititystauluunsa ja lähetä sinne vain tuon tilin liikenne:
ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100Tämä toimii vain, jos tunneli ei ole jo oletusreitti. Käynnistä asiakas valitsimella --route-nopull tai suodata työnnetty uudelleenohjaus valitsimella --pull-filter ignore "redirect-gateway" OpenVPN 2.4:ssä ja uudemmissa, ja lisää sitten taulumerkintä itse. Muuten molemmat oletukset ovat olemassa ja alemman prioriteetin voittaa. Tarkoituksellinen versio tästä on ohjata oletusreitti tunnelin yhdyskäytävään tai tehdä se katkaisuskriptistä: se pitää liikenteen poissa internetistä, kun tunneli putoaa, mutta se on hätäkatkaisin, ei valitsin, ja se pysyy, kunnes joku poistaa sen.
Vahvempi versio on verkon nimiavaruus. Luo se, aja asiakas sen sisällä ja käynnistä sovellus valitsimella ip netns exec. Mikään nimiavaruuden ulkopuolella ei näe tunnelin liitännäistä, joten sovellus ei voi vahingossa pudota takaisin isännän reitille. Hinta on todellinen: nimiavaruus tarvitsee veth-parin fyysiseen verkkoon pääsemiseksi ja oman resolver-tiedoston, koska liitoksen nimiavaruus ei jaa isännän ratkaisuasetuksia.
Kaksi vikatilaa selittää useimmat vuodot. Nimien ratkaisu tapahtuu yhä isännän resolverissa, joten kysely lähtee tunnelin ulkopuolelle, vaikka TCP-yhteys menee sisään. Ja IPv6 tarvitsee oman ip -6 rule-säännön, koska v4-sääntö ei kata sitä.
Windows ja macOS: rajaa palomuuri tai luovuta välityspalvelin
Windowsillakaan ei ole sovelluskohtaista reittivalitsinta, mutta sen palomuurisäännöt voidaan rajata profiiliin, ja VPN-sovitin voidaan luokitella „julkiseksi“, kun kotiverkko pysyy „yksityisenä“. Luo ohjelmalle lähtevät estosäännöt „yksityinen“- ja „verkkotunnus“-profiileihin, jätä „julkinen“ avoimeksi, ja sovellus pääsee verkkoon vain tunnelin kautta. Aseta ensin yhteyden verkkoluokka ja vahvista sitten, että sääntö osui palomuurin valvontapaneelissa. Se on esto, ei reitti: se epäonnistuu suljetusti, kun tunneli putoaa, eikä se voi pysäyttää sovellusta, joka jättää palomuurin huomiotta.
macOS seuraa samaa logiikkaa muilla työkaluilla. SSH:n kautta tavoitettava SOCKS-kuuntelija on vähiten tunkeileva vaihtoehto, koska ssh -D 1080 user@host luo yhden paikallisen portin ja vain sen käyttöön määritetyt sovellukset kulkevat sitä kautta. Sääntö pf voi estää ohjelman käyttäjän tai ryhmän mukaan, mutta se ei silti voi valita tunnelia vain kyseiselle ohjelmalle. Tunnelblick ei voi suodattaa verkkotunnuksen mukaan lainkaan, koska reitit toimivat osoitteilla; OpenConnectin käyttäjät turvautuvat valitsimeen vpn-slice, kun palvelin työntää liian laajan etuliiteluettelon.
Kaksi kiertotietä kattaa sen, minkä alustan työkalut jättävät huomaamatta. Verkkotunnuksen mukaan välityspalvelinta vaihtavat selainlaajennukset ovat käytännöllinen vastaus „vain tämä sivusto“ -pyyntöön, koska ne toimivat sovelluskerroksessa, jossa nimet vielä ovat olemassa; ne kattavat yhden selaimen eivätkä mitään muuta. Karkea tapa on ajaa toimittajan asiakas virtuaalikoneessa, jolloin vieras omistaa reittimuutoksen ja isäntä pitää polkunsa, kahden ylläpidettävän verkkopinon hinnalla.
SOCKS-hyppy työkaluille, joilla ei ole sidontavaihtoehtoa
Useimmat sovellukset voidaan osoittaa HTTP- tai SOCKS-välityspalvelimeen, vaikka ne eivät tietäisi liitännäisistä mitään. SSH-asiakas tarjoaa sellaisen ilman mitään muutosta palvelinpuolella:
ssh -N -D 127.0.0.1:9999 [email protected]Kaikki, mikä on määritetty käyttämään tuota porttia, lähtee bastionilta, kun muu työpöytä pitää tavallisen yhteytensä. Tunnelin osoitteeseen sidottu paikallinen 3proxy-esiintymä tekee saman yhdelle portille ilman SSH:ta, ja stunnel kattaa yhden TLS:ään käärityn portin. Rajat ovat käytännöllisiä: välityspalvelin kuljettaa vain protokollia, jotka osaavat käyttää sitä, UDP tarvitsee SOCKS5 UDP -liitoksen, jota monien asiakkaiden „SOCKS5“-asetus ei ota käyttöön, ja DNS on ratkaistava välityspalvelimen kautta (socks5h curlissa), muuten nimi vuotaa paikalliseen resolveriin.
Pidä kuuntelija loopbackissa, ellet tarvitse sitä toisella koneella.
Varmista polku kaappauksella, älä tilaviestillä
Sovelluksen tilan ikkunat kuvaavat asetusta, eivät pakettia. Kaappaa molemmilta liitännäisiltä ja vertaa:
tcpdump -i any -n port 443
ss -tnp | grep 443Jos yhteys näkyy fyysisellä liitännäisellä ilman vastaavaa merkintää tunnelissa, valitsin ei ole voimassa, mitä asiakas tahansa raportoi. Tarkista IPv6 ja resolveri erikseen ja tarkista toinen polku, kuten apuprosessi tai peritty järjestelmän välityspalvelin.
Valitse sitten raja, joka vastaa vaatimusta: välityspalvelin riittää yhdelle sivustolle, UID-sääntö riittää yhdelle tilille, palomuuriprofiili riittää, kun yhteyden on epäonnistuttava suljetusti, ja nimiavaruus on ainoa vaihtoehto, joka kätkee tunnelin kaikelta sen ulkopuolelta.