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.

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

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 100

Tä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 443

Jos 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.

Aiheeseen liittyvät artikkelit