Den galne føresetnaden er at ein VpnService-app vippar ein systembrytar, og at telefonen frå då av er verna. Det som faktisk skjer, er smalare: appen ber om samtykke, byggjer eit grensesnitt, les og skriv pakkar gjennom ein filskildring, og gjev grensesnittet tilbake når han stoppar. Berre éin slik tunnel kan vere levande om gongen, og systemet kan ta han utan å spørje. Det meste av den forvirrande åtferda folk gjev protokollen skulda, kjem frå den eigarmodellen.

Behandle kvar livssyklusovergang som ein del av designet og ikkje som eit randtilfelle.

Myte: appen slår på VPN-en på telefonen

Flyten startar med VpnService.prepare(), som returnerer ein Intent brukaren må godta, og held fram med establish(), som framleis kan feile etterpå av årsaker appen ikkje styrer. Å opprette ein ny tunnel deaktiverer det første grensesnittet og erstattar systemvarselet. Ingen stad i den sekvensen eig appen ein einingsomfattande brytar; han eig skildringa han fekk, og pakkane som landar på henne. Sjølv det varige varselet høyrer til systemet og ikkje til designet av appen.

Fordi grensesnittet blir gjeve og ikkje gripe, kan ein annan klient ta plassen når som helst. Appen får vite det gjennom eit tilbakekall, ikkje gjennom ein returverdi.

At appen blir tvinga stoppa, synest i varselspanelet av same grunn: systemet rapporterer kva det har gjeve, ikkje kva appen valde å vise.

Myte: samtykket blir gjeve éin gong

Når systemet overlet tunnelen til ein annan klient, sender det ein tilbakekallingstransaksjon på binderen som basisklassen returnerer frå onBind(). Ein app som erstattar den binderen med sin eigen, må videresende tilbakekallingstransaksjonen sjølv, elles blir VpnService.onRevoke() aldri utløyst, og tenesta held fram med å skrive til ei skildring som ikkje finst lenger. Godkjenninga kan også trekkjast tilbake av brukaren, og systemet kan stoppe tenesta under ein omstart eller ei alltid-på-gjenoppkopling.

Å handtere det er konkret arbeid og ikkje ei logglinje: slutt å lese skildringa, lukk henne, tøm tilkopla-flagget og fortel brukaren kva tilstand han er i. Deretter avgjer om appen skal gjenopprette, spørje igjen eller vente, for i ein alltid-på-konfigurasjon kan systemet bringe tenesta tilbake sjølv.

Ein app som behandlar tilbakekalling som eit unntak og ikkje som ein tilstand, vil rapportere tilkopla medan kvar pakke han skriv blir forkasta, og det er den verste feilmodusen som finst for eit personvernverktøy.

Myte: grensesnittet filtrerer trafikk for deg

Det som kjem inn, er rå IP. Å fange eller filtrere betyr å parse IP-, TCP-, UDP- og IPv6-hovud, følgje straumar og skrive svar tilbake til skildringa, noko som gjer ein fangeapp til ein liten nettverksstakk og ikkje ein systemfasilitet. protect() finst for at appens eigen transportsokkel skal gå utanom tunnelen sin i staden for å fange seg sjølv, og han returnerer ein boolsk verdi som fortener ein sjekk på kvar sokkel som blir oppretta etter at tunnelen er oppe.

Listene til byggjaren over tillatne og forbodne apper avgjer kven sin trafikk som kjem inn i grensesnittet. Dei gjev ikkje tilgang til nyttelast utover IP-pakkane grensesnittet ber, og ingen API eksponerer tunnelen til ein annan klient eller listar VPN-profilane til systemet. Nettverksfunksjonar kan seie at eit nettverk er VPN-transport, men ikkje kven sin tunnel det er.

Difor får statusspørsmål om andre apper motstridande svar: informasjonen er rett og slett ikkje eksponert for prosessen din.

Kva livssyklusen faktisk krev

Følg tilstandane du styrer: førebudd, oppretta, tilbakekalla, stoppa. Gjenoppkopling bør vere nedriving etterfølgt av oppretting, med éin eigar av skildringa og transportsokkelen, fordi to komponentar som kappast om å opprette, vil slåst om den eine ledige plassen. Bakgrunnsstartar er avgrensa på moderne Android, så ein oppstartsbroadcast er inga garanti; bruk ei forgrunnsteneste med varselet sitt der API-nivået tillèt det.

Logg overgangen og ikkje berre sluttilstanden, og hald tilstandsmaskinen liten nok til å teste kvar veg. Ein tilstand du ikkje kan nå i ein test, er ein tilstand du møter i felt utan ein logg.

Test livssyklusen på ein eining

Emulatorar kan etterlikne tilkopling, men ikkje samtykke- og tilbakekallingsvegen overtydande, så køyr desse på ei ekte eining med ein annan VPN-klient installert for å stele plassen.

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

Start tunnelen, stadfest varselet og grensesnittet, kopla deretter til den andre klienten og sjå om tilbakekallingstilbakekallet køyrer og tilstanden blir tømd. Tvangstopp appen og sjekk om noko framleis rapporterer ei levande skildring.

Gjenta sekvensen etter ein alltid-på-omstart, fordi den vegen er annleis enn ei brukarstarta tilkopling. Det du leitar etter, er ikkje eit grønt ikon, men prov på at appen slutta å bruke ei skildring han ikkje lenger eigde.

Relaterte artiklar