Android always-on VPN: kaip pirmiausia išsprendžiamas galinio taško vardas
Android blokuoja srautą dar iki tunelio atsiradimo, tačiau klientas vis tiek turi išspręsti savo galinį tašką. Štai tvarka ir vieta, kurioje užstringama.
Telefonas paleidžiamas iš naujo, always-on įjungtas, „blokuoti ryšius be VPN“ įjungta, o tunelis taip ir nepakyla. Niekas nesukonfigūruota neteisingai: blokavimas atlieka savo darbą, o paties kliento bandymas pasiekti savo galinį tašką jam taip pat paklūsta. Galinio taško vardas turi būti išspręstas iki tunelio atsiradimo, kliento, kuriam leidžiama kalbėtis su tinklu, kai visoms kitoms programoms neleidžiama. Suvokimas, kuris komponentas tai daro ir kokia tvarka, šią mįslę paverčia konfigūracijos klausimu.
Ko iš tikrųjų prašo VPN kūrėjas
Android VPN programa neperduoda platformai serverio adreso. Ji sukuria vietinę sąsają: tunelio adresus ir maršrutus, resolverius, kuriuos programos turi naudoti jo viduje, o tada establish() grąžina failo deskriptorių, kurį programa skaito ir rašo kaip neapdorotus IP paketus. Nuotolinis galinis taškas tame kūrėjyje visai nepasirodo.
Tai pagrindinis struktūrinis faktas. Platforma sukuria tun sąsają ir jai taiko politiką; programa įgyvendina perdavimą vartotojo erdvėje, tai reiškia, kad pati programa išsprendžia savo galinio taško vardą ir atidaro šifruotą ryšį. Todėl galinis taškas kaip prieglobos vardas yra įmanomas — ne todėl, kad platforma palaiko vardus, o todėl, kad platforma galinio taško niekada nemato.
Vienas kūrėjo laukas vis dėlto priima adresus: DNS serveriai. Jie turi būti skaitiniai resolverių adresai, dažniausiai tie, kuriuos operatorius nori užklausti per tunelį. Šis laukas aprašo, kur programos siunčia užklausas po to, kai tunelis pakyla. Jis nieko nesako apie tai, kaip klientas randa galinį tašką, ir būtent šių dviejų nuostatų sutapatinimas yra sumaišties pradžia.
Du DNS klausimai, o ne vienas
Pirmasis klausimas: kur programos siunčia užklausas, kai tunelis jau pakilęs? Atsakymas yra resolverio adresas tunelio viduje, pasiekiamas per tun sąsają ir iš prigimties skaitinis.
Antrasis klausimas: kaip klientas randa savo galinį tašką iki to tunelio atsiradimo? Ta paieška vyksta už tunelio, pagrindiniame tinkle, kliento procese. Ji gali naudoti vardą ir turi naudoti resolverį, kurį įrenginys pasiekia be VPN.
| Stage | Who resolves | Path | Failure looks like |
|---|---|---|---|
| Endpoint lookup | The VPN app | Underlying network, protected socket | Never connects; no tunnel interface traffic |
| Peer authentication | Client and server | Tunnel transport | Connects then drops; certificate or key error |
| Private name lookup | Apps via the tunnel | Resolver inside the tun | Tunnel up, internal sites do not resolve |
Trys etapai, trys skirtingi simptomai. Viena klaidos žinutė „nepavyksta prisijungti“ juos suplaka, todėl žmonės pradeda taisyti DNS serverio lauką, kad išspręstų problemą, kuri kyla dar prieš tą lauką perskaitant.
Kodėl bootstrap gali užstrigti
Always-on su įjungtu blokavimu reiškia, kad srautas, kuris nėra VPN viduje, atmetamas, įskaitant programos, kuriai priklauso VPN, srautą. Išėjimas yra aiškus: programa iškviečia protect() ant lizdo, kuris jį pririša prie pagrindinio tinklo, todėl jis apeina tunelį ir yra išleidžiamas. Kiekvienas VPN klientas turi tai daryti savo perdavimui, kitaip niekada nepasieks serverio.
Dabar apsvarstykime diegimą, kuriame vienintelis resolveris, žinantis galinio taško vardą, pats yra tunelio viduje. Klientui reikia tunelio vardui išspręsti ir vardo tuneliui sukurti. Tai tikra žiedinė priklausomybė, ir jokia kliento konfigūracija jos neišsprendžia. Tai projektavimo klaida, o ne klaida programoje.
Laikas atskleidžia tą pačią priklausomybę švelnesnėmis formomis. Įjungimo metu prieš pirmąjį atrakinimą įrenginys gali dar neturėti tinkamo tinklo; captive portal atveju tinklas yra, bet blokuoja viską, išskyrus portalą; pereinant iš Wi-Fi į mobilųjį tinklą, apsaugoto lizdo pagrindinis tinklas pasikeičia, ir klientas turi tai pastebėti ir iš naujo išspręsti. Kiekvienas iš jų yra bootstrap įvykis, ir kiekvieną verta sąmoningai išbandyti, o ne atrasti 3 valandą nakties.
Kodėl atsakymo užfiksavimas nėra sprendimas
Viliantis apeiti kelias yra vieną kartą išspręsti vardą ir gautą adresą įklijuoti į skaitinį lauką, arba užkoduoti jį individualiame rinkinyje. Atrodo, kad veikia, ir paverčia vardą nuotrauka. Kai operatorius perkelia galinį tašką — migracija, anycast pakeitimas, naujas regioninis adresas — klientas toliau skambina senajam, ir niekas sąsajoje nepaaiškina kodėl.
DNS įrašai turi gyvavimo trukmę būtent todėl, kad atsakymai galėtų keistis; podėliavimas apibrėžiamas pagal tą trukmę, o ne amžinai. Atsakymo užfiksavimas atmeta mechanizmą, kuris vardą daro geresnį už adresą, ir kartu išlaiko operacines sąnaudas dėl to, kad buvo naudotas vardas.
Užfiksavimas dažnai eina kartu su antru blogu įpročiu: silpninti tapatybės patikrą, nes ryšys dabar nepavyksta kitaip. Serverio tapatybės tikrinimas nėra bootstrap problemos dalis, o jo silpninimas iškeičia DNS nepatogumą į perėmimo riziką.
Sprendimai, atlaikantys paleidimą iš naujo
Ilgaamžė sandara yra neįspūdinga. Naudokite klientą, kuris teisingai įgyvendina apsaugotus lizdus ir išsprendžia savo galinį tašką pagrindiniame tinkle, ir suteikite jam galinio taško vardą, kuris išsprendžiamas viešai arba per resolverį, pasiekiamą prieš tunelį. Palikite blokavimą įjungtą; visiškas jo išjungimas, kad veiktų DNS, pašalina savybę, dėl kurios diegimas egzistuoja.
Kur galinis taškas turi likti privatus, suteikite aiškų bootstrap kelią, kurį platforma gali naudoti — resolverį, pasiekiamą be tunelio, arba operatoriaus palaikomą valdymo ryšį — ir laikykite tą išimtį siaurą bei priklausančią politikai, o ne vartotojo jungikliui. Android VpnService dokumentacija yra nuoroda į tai, ką platforma garantuoja dėl apsaugos ir gyvavimo ciklo, o VpnService.Builder nuoroda patvirtina, kad DNS laukas priima skaitinius adresus.
Tada patikrinkite tris etapus iš eilės naujame ryšyje po paleidimo iš naujo: galinio taško vardas išsprendžiamas, tunelis užmezgamas ir partneris autentifikuojamas, o privatus vardas išsprendžiamas per tunelio resolverį. Jei pirmasis etapas nepavyksta, niekas vėlesnis negali veikti, o taisymas priklauso bootstrap keliui — niekada resolverio laukui.
- Galinio taško sprendimas vyksta programoje, už tunelio, apsaugotame lizde.
- Kūrėjo DNS laukas skirtas programoms tunelio viduje, o ne paties kliento galiniam taškui.
- Resolveris, pasiekiamas tik per tunelį, yra aklavietė, o ne lėtas startas.
- Po paleidimo iš naujo atskirai išbandykite galinį tašką, autentifikavimą ir privatų vardo sprendimą.