Klaidinga prielaida yra ta, kad VpnService programėlė perjungia sistemos jungiklį ir nuo to momento telefonas yra apsaugotas. Iš tikrųjų vyksta siauresnis dalykas: programėlė prašo sutikimo, sukuria sąsają, skaito ir rašo paketus per failo deskriptorių, o sustojusi sąsają grąžina. Vienu metu gyvas gali būti tik vienas toks tunelis, o sistema gali jį atimti nepaklaususi. Didžioji dalis painaus elgesio, kurį žmonės priskiria protokolui, kyla būtent iš šio nuosavybės modelio.

Kiekvieną gyvavimo ciklo perėjimą traktuokite kaip dizaino dalį, o ne kaip kraštinį atvejį.

Mitas: programėlė įjungia telefono VPN

Srautas prasideda nuo VpnService.prepare(), kuris grąžina Intent, kurį vartotojas turi priimti, ir tęsiasi su establish(), kuris vėliau vis tiek gali nepavykti dėl priežasčių, kurių programėlė nekontroliuoja. Antro tunelio sukūrimas išjungia pirmąją sąsają ir pakeičia sistemos pranešimą. Niekur šioje sekoje programėlė neturi viso įrenginio jungiklio; ji turi jai suteiktą deskriptorių ir paketus, kurie ant jo patenka. Net nuolatinis pranešimas priklauso sistemai, o ne programėlės dizainui.

Kadangi sąsaja suteikiama, o ne atimama, kitas klientas gali užimti vietą bet kuriuo metu. Programėlė apie tai sužino per atgalinį iškvietimą, o ne per grąžinamą reikšmę.

Priverstinis programėlės sustabdymas matomas pranešimų juostoje dėl tos pačios priežasties: sistema praneša, ką suteikė, o ne ką programėlė pasirinko rodyti.

Mitas: sutikimas duodamas vieną kartą

Kai sistema perduoda tunelį kitam klientui, ji siunčia atšaukimo operaciją per binder, kurį bazinė klasė grąžina iš onBind(). Programėlė, kuri tą binder pakeičia savo, privalo pati persiųsti atšaukimo operaciją, kitaip VpnService.onRevoke() niekada nebus suaktyvintas ir tarnyba toliau rašys į deskriptorių, kurio nebėra. Sutikimą gali atšaukti ir vartotojas, o sistema gali sustabdyti tarnybą paleidimo iš naujo ar visada įjungto prisijungimo metu.

Tvarkytis su tuo yra konkretus darbas, o ne žurnalo eilutė: nustokite skaityti deskriptorių, uždarykite jį, išvalykite prisijungimo vėliavėlę ir pasakykite vartotojui, kokioje būsenoje jis yra. Tada nuspręskite, ar programėlė turi iš naujo sukurti, dar kartą paklausti ar laukti, nes visada įjungtoje konfigūracijoje sistema gali pati grąžinti tarnybą.

Programėlė, kuri atšaukimą traktuoja kaip išimtį, o ne kaip būseną, praneš apie prisijungimą, nors kiekvienas jos rašomas paketas yra išmetamas, ir tai yra blogiausias įmanomas gedimo režimas privatumo įrankiui.

Mitas: sąsaja filtruoja srautą už jus

Tai, kas atvyksta, yra neapdorotas IP. Užčiuopimas ar filtravimas reiškia IP, TCP, UDP ir IPv6 antraščių analizę, srautų stebėjimą ir atsakymų rašymą atgal į deskriptorių, o tai užčiuopimo programėlę paverčia mažu tinklo steku, o ne sistemos priemone. protect() egzistuoja tam, kad pačios programėlės transporto lizdas apeitų savo tunelį, o ne užčiuoptų save, ir jis grąžina loginę reikšmę, kurią verta patikrinti kiekviename lizde, sukurtame po tunelio sukūrimo.

Konstruktoriaus leidžiamų ir draudžiamų programėlių sąrašai nusprendžia, kieno srautas patenka į sąsają. Jie nesuteikia prieigos prie naudingosios apkrovos už sąsajos nešamų IP paketų, ir jokia API neatskleidžia kito kliento tunelio ar išvardija sistemos VPN profilius. Tinklo galimybės gali pasakyti, kad tinklas yra VPN transportas, bet ne tai, kieno tai tunelis.

Štai kodėl būsenos klausimai apie kitas programėles sulaukia prieštaringų atsakymų: informacija tiesiog nėra atskleista jūsų procesui.

Ko gyvavimo ciklas iš tikrųjų reikalauja

Stebėkite būsenas, kurias kontroliuojate: paruošta, sukurta, atšaukta, sustabdyta. Prisijungimas iš naujo turėtų būti išardymas ir po jo sukūrimas, su vienu deskriptoriaus ir transporto lizdo savininku, nes du komponentai, lenktyniaujantys dėl sukūrimo, kovos dėl vienintelės laisvos vietos. Fono paleidimai šiuolaikiniame Android yra apriboti, todėl paleidimo transliacija nėra garantija; naudokite priekinės plokštumos tarnybą su jos pranešimu ten, kur API lygis leidžia.

Registruokite perėjimą, o ne tik galutinę būseną, ir laikykite būsenos mašiną pakankamai mažą, kad būtų galima išbandyti kiekvieną kelią. Būsena, kurios negalite pasiekti teste, yra būsena, kurią sutiksite lauke be žurnalo.

Išbandykite gyvavimo ciklą įrenginyje

Emuliatoriai gali falsifikuoti ryšį, bet neįtikinamai sutikimo ir atšaukimo kelią, todėl vykdykite tai realiame įrenginyje su įdiegtu antru VPN klientu, kuris pavogs vietą.

adb shell dumpsys connectivity | grep -i -A3 vpn
adb shell dumpsys activity services | grep -i -A2 vpnservice
adb logcat -s VpnService:V AndroidRuntime:E
adb shell am force-stop com.example.vpnapp

Paleiskite tunelį, patvirtinkite pranešimą ir sąsają, tada prijunkite kitą klientą ir stebėkite, ar vykdomas atšaukimo atgalinis iškvietimas ir ar būsena išsivalo. Priverstinai sustabdykite programėlę ir patikrinkite, ar kas nors dar praneša apie gyvą deskriptorių.

Pakartokite seką po visada įjungto paleidimo iš naujo, nes tas kelias skiriasi nuo vartotojo pradėto prisijungimo. Jūs ieškote ne žalios piktogramos, o įrodymo, kad programėlė nustojo naudoti deskriptorių, kurio jau nebevaldė.

Susiję straipsniai