Kaip nukreipti vieną programą per VPN be viso kompiuterio
Jokia nevaldoma darbalaukio aplinka nesiūlo VPN jungiklio kiekvienam procesui. Pasirinkite sluoksnį, kuris parenka srautą: susietas lizdas, UID taisyklė, ugniasienės profilis arba SOCKS šuolis.
VPN klientas prisijungia, naršyklė veikia, o ta viena komanda, kuri iš tikrųjų jums rūpi, vis tiek išeina per namų ryšį. Arba nutinka priešingai: tunelis užima numatytąjį maršrutą, ir vietinis failų serveris dingsta iš darbalaukio. Su tuo susidūriau kūrimo agente, kuriam reikėjo pasiekti vidinį artefaktų veidrodį, kai likusi pagrindinės mašinos dalis liko biuro LAN tinkle, o klientas pasiūlė lygiai du pasirinkimus: visas srautas arba nieko. Abiem kryptimis prašymas tas pats, ši programa, o ne visas kompiuteris, ir dauguma klientų tam neturi žymimuko, nes maršrutų lentelė niekada nežinojo, kas yra programa.
Kodėl maršrutų lentelė nemato jūsų programos
Kai procesas siunčia paketą, dėklas ieško paskirties adreso maršrutų lentelėje. Nei vykdomosios bylos pavadinimas, nei prievadas į tą paiešką neįeina. Domenų vardai nepavyksta dėl tos pačios priežasties: tunelis neša srautą į adresą, o kai vardas išsprendžiamas į adresą, maršrutizavimas yra vienintelė svirtis, kurią branduolys dar turi. Todėl „VPN tik šiai svetainei“ galiausiai reiškia tarpinį serverį, o „VPN tik šiai programai“ reiškia vieną iš mažo mechanizmų rinkinio.
| 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 |
Nė vienas iš jų nėra maršrutas pagal procesą. Kiekvienas perkelia sprendimą į sluoksnį, kuris mato programą, naudotoją arba pačios programos konfigūraciją.
Vienas tikslas vis dar yra maršrutas, o ne programos taisyklė. macOS įprastas receptas yra nuimti žymą „Siųsti visą srautą per VPN“ ir pridėti pagrindinio kompiuterio maršrutą: sudo route add -host internal-tuner.example -interface ppp0, kuris vėl pašalinamas su sudo route delete -host internal-tuner.example -interface ppp0. Pirmiausia perskaitykite sąsajos pavadinimą iš ifconfig, nes ppp0 yra tik pavyzdys. Pakaitos simboliai pagrindinio kompiuterio maršrute neveikia, todėl paslaugai, kuri kalba su keliais vardais, reikia po vieną įrašą kiekvienam vardui, ir taisyklė apima kiekvieną mašinos procesą, o ne tą, kurį turėjote omenyje.
Susiekite lizdą su tunelio adresu
Kai valdote klientą, susiejimas yra pigiausias parinkiklis. Lizdas, susietas su vietiniu tunelio adresu, išeina per tą sąsają tol, kol ten yra maršrutas į paskirties vietą, o visa kita mašinoje išlaiko įprastą kelią. Subtilumas tas, kad susiejimas parenka šaltinio adresą, o maršrutų lentelė vis dar parenka išėjimą. Vien susiejimas neperkelia srauto, kuris neturi maršruto į tunelį, ir būtent ši klaida slypi už daugumos pranešimų „susiejau, o jis vis tiek išeina ne ta puse“.
import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))Aukštesnio lygio įrankiai siūlo tą pačią idėją: curl --interface 10.8.0.2, PHP CURLOPT_INTERFACE ir source_address argumentas Python HTTP klientuose. Adresas turi priklausyti tuneliui, o rašybos klaida čia nepavyksta kaip įprasta ryšio klaida, o ne kaip maršrutizavimo skundas. Susiejimas su įrenginio pavadinimu, o ne adresu, yra Linux privilegija ir nepersikelia į Windows ar macOS, todėl perkeliami scenarijai perduoda adresą.
Linux: sutapkite savininką, o ne programos pavadinimą
Branduolys gali sutapinti lizdo savininką, todėl skirta paskyra tampa parinkikliu. Įdėkite tunelį į savo maršrutų lentelę ir siųskite ten tik tos paskyros srautą:
ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100Tai veikia tik jei tunelis jau nėra numatytasis maršrutas. Paleiskite klientą su --route-nopull, arba filtruokite stumiamą peradresavimą su --pull-filter ignore "redirect-gateway" OpenVPN 2.4 ir naujesnėse versijose, tada patys pridėkite lentelės įrašą. Priešingu atveju egzistuoja abu numatytieji, ir laimi tas, kurio prioritetas mažesnis. Sąmoninga to versija yra nukreipti numatytąjį maršrutą į tunelio šliuzą arba tai daryti atjungimo scenarijuje: tai laiko srautą už interneto ribų, kai tunelis krinta, bet tai yra išjungiklis, o ne parinkiklis, ir jis lieka, kol kas nors jį pašalins.
Stipresnė versija yra tinklo vardų erdvė. Sukurkite ją, paleiskite klientą viduje ir paleiskite programą su ip netns exec. Niekas už vardų erdvės ribų nemato tunelio sąsajos, todėl programa negali atsitiktinai grįžti prie pagrindinio kompiuterio maršruto. Kaina reali: vardų erdvei reikia veth poros, kad pasiektų fizinį tinklą, ir savo resolver failo, nes prijungimo vardų erdvė nesidalija pagrindinio kompiuterio sprendimo nustatymais.
Du gedimo režimai paaiškina daugumą nuotėkių. Vardų sprendimas vis dar vyksta pagrindinio kompiuterio resolveryje, todėl užklausa išeina už tunelio ribų net kai TCP ryšys eina į vidų. O IPv6 reikia savo ip -6 rule, nes v4 taisyklė jo neapima.
Windows ir macOS: apribokite ugniasienę arba perduokite tarpinį serverį
Windows taip pat neturi maršruto parinkiklio pagal programą, bet jo ugniasienės taisykles galima apriboti profiliu, o VPN adapterį galima priskirti „viešam“, kol namų LAN lieka „privatus“. Sukurkite išeinančias blokavimo taisykles programai profiliuose „privatus“ ir „domeno“, palikite „viešą“ atvirą, ir programa pasieks tinklą tik per tunelį. Pirmiausia nustatykite ryšio tinklo kategoriją, tada patvirtinkite, kad taisyklė sutapo ugniasienės stebėjimo skydelyje. Tai blokavimas, o ne maršrutas: jis nepavyksta uždaroje būsenoje, kai tunelis krinta, ir negali sustabdyti programos, kuri ignoruoja ugniasienę.
macOS laikosi tos pačios logikos su kitais įrankiais. SOCKS klausytojas, pasiekiamas per SSH, yra mažiausiai invazyvus variantas, nes ssh -D 1080 user@host sukuria vieną vietinį prievadą, ir tik tam sukonfigūruotos programos eina tuo keliu. pf taisyklė gali blokuoti programą pagal naudotoją ar grupę, bet vis dar negali parinkti tunelio vien tai programai. Tunnelblick visiškai negali filtruoti pagal domeną, nes maršrutai dirba su adresais; OpenConnect naudotojai griebiasi vpn-slice, kai serveris stumia per platų prefiksų sąrašą.
Du apejimo būdai padengia tai, ką platformos įrankiai praleidžia. Naršyklės plėtiniai, keičiantys tarpinį serverį pagal domeną, yra praktiškas atsakymas į „tik ši svetainė“, nes jie veikia programos sluoksnyje, kur vardai dar egzistuoja; jie apima vieną naršyklę ir nieko daugiau. Šiurkštus būdas yra paleisti tiekėjo klientą virtualioje mašinoje, kad svečias valdytų maršruto pakeitimą, o pagrindinė mašina išlaikytų savo kelią, už dviejų tinklo dėklų priežiūros kainą.
SOCKS šuolis įrankiams be susiejimo parinkties
Daugumą programų galima nukreipti į HTTP arba SOCKS tarpinį serverį net kai jos nieko nežino apie sąsajas. SSH klientas pateikia vieną be jokių pakeitimų serverio pusėje:
ssh -N -D 127.0.0.1:9999 [email protected]Viskas, kas sukonfigūruota naudoti tą prievadą, išeina prie bastiono, o likęs darbalaukis išlaiko įprastą ryšį. Vietinė 3proxy kopija, susieta su tunelio adresu, daro tą patį vienam prievadui be SSH, o stunnel apima vieną TLS apvyniotą prievadą. Ribos praktiškos: tarpinis serveris neša tik protokolus, kurie moka juo naudotis, UDP reikia SOCKS5 UDP asociacijos, kurios daugelio klientų „SOCKS5“ nustatymas neįjungia, o DNS turi išspręsti tarpinis serveris (socks5h curl), kitaip vardas nuteka į vietinį resolverį.
Laikykite klausytoją loopback sąsajoje, nebent jo reikia kitai mašinai.
Tikrinkite kelią užfiksuodami, o ne būsenos pranešimu
Programos būsenos langai apibūdina nustatymą, o ne paketą. Užfiksuokite abiejose sąsajose ir palyginkite:
tcpdump -i any -n port 443
ss -tnp | grep 443Jei ryšys pasirodo fizinėje sąsajoje be atitinkamo įrašo tunelyje, parinkiklis neveikia, kad ir ką praneštų klientas. Patikrinkite IPv6 ir resolverį atskirai, ir patikrinkite, ar yra antras kelias, pavyzdžiui, pagalbinis procesas ar paveldėtas sistemos tarpinis serveris.
Tada pasirinkite ribą, kuri atitinka reikalavimą: vienai svetainei pakanka tarpinio serverio, vienai paskyrai pakanka UID taisyklės, ugniasienės profilio pakanka, kai ryšys turi nepavykti uždaroje būsenoje, o vardų erdvė yra vienintelė parinktis, kuri paslepia tunelį nuo visko, kas yra už jo.