Android-VPN uden root: hvem ejer samtykke, ruter og blokering
Samtykke, TUN-grænsefladen og systemets blokeringspolitik er tre forskellige tilladelser. Spor hvilken komponent der ejer hver af dem, før du gennemgår en Android-VPN-app.
Root er ikke det, der gør en Android-VPN-app i stand til at føre trafik, blokere lækager eller overleve en genstart. Folk opsummerer det hele som „appen har VPN-tilladelse“, og det skjuler tre adskilte mekanismer: en samtykketilladelse fra brugeren, en pakkegrænseflade som systemet opretter, og en blokeringspolitik på platformen, som ikke er appens at definere. At gennemgå et Android-VPN-design betyder at spørge, hvilken af de tre en påstand faktisk hviler på, fordi hver har en anden ejer og en anden fejltilstand.
Samtykke kommer gennem en systemaktivitet
VpnService.prepare() giver ikke noget. Den returnerer et intent til systemets samtykkeaktivitet, når samtykke mangler, og appen starter den dialog, så brugeren kan godkende tjenesten. At starte appens egen proces, føje en tilladelse til manifestet eller vise en tilpasset „aktivér VPN“-skærm opretter ikke tilladelsen.
Tilladelsen er også afgrænset. Den tilhører en pakke i en brugerprofil, så den personlige kopi og arbejdskopien er separate beslutninger, og en enhedsejer kan forberede en administreret profil anderledes end en personlig. Hvis dialogen aldrig vises, og prepare() returnerer null, findes samtykket allerede for den pakke i den profil; det er ikke bevis for, at appen er troværdig, kun at tilladelsen er på plads.
Grænsefladen er en anmodning, som systemet opfylder
Efter samtykke beskriver appen, hvad den vil have, med VpnService.Builder: adresser, ruter, DNS-servere, MTU og, hvor det understøttes, de apps der skal medtages eller udelades. establish() beder systemet om at oprette tunngrænsefladen og lede den matchende trafik ind i den. Systemet ejer rutningsbeslutningen; appen modtager fildeskriptoren og skal derefter gøre noget nyttigt med pakkerne.
| What you observe | Who actually owns it |
|---|---|
| VPN consent dialog | The system, triggered by prepare() |
| Routes, DNS and app lists | The app requests them; the system applies them |
| One active VPN per profile | The platform; a new service replaces the old one |
| Always-on and block-without-VPN | Device policy enforced by the platform |
Den tabel er arkitekturen på ét sted. Appen deltager i pakkehåndtering; den ejer ikke grænsefladen, rutetabellen eller antallet af tjenester, der må køre.
Tunnelsocket skal undslippe sin egen tunnel
Forbindelsen, der bærer den krypterede trafik, er selv en socket. Hvis den rutes tilbage i den grænseflade, appen netop har oprettet, afhænger tunnelen af tunnelen og går i stå. VpnService.protect() binder den socket til det underliggende netværk, så den omgår optagelsen, og derfor beskytter en korrekt klient sin ydre socket før det første håndtryk.
adb shell dumpsys connectivity | grep -i -A5 vpn
adb shell settings get global always_on_vpn_app
adb shell settings get global always_on_vpn_lockdown
Disse kommandoer viser det installerede VPN-netværk, pakken med altid tændt og om låsning er sat. De er kun læseobservationer: hvis værdierne ikke stemmer med det, designet hævder, handler påstanden om appens grænseflade og ikke systemets tilstand.
Blokering kan tilhøre platformen
Android dokumenterer en politik, der blokerer forbindelser, som ikke bruger VPN. Den håndhævelse er en platformskontrakt, ikke en app, der gentager forbindelsesforsøg i en løkke. Kontakten findes i enhedens VPN-indstillinger som Bloker forbindelser uden VPN, og på en administreret enhed kan ejeren slå den til for hele profilen. Forskellen er vigtig, når du vurderer en markedsføringspåstand: en klient kan vise et låseikon og genoprette forbindelse aggressivt, mens direkte trafik stadig er mulig, eller omfattede apps kan forblive offline, fordi systemet håndhæver låsningen.
Et låseikon tegnes af appen, så det beviser kun, at appen tror, den er forbundet. Om en anden app mister sin netværksadgang, afgøres af platformen, så den nyttige kontrol er at se den app fejle, mens tunnelen er oppe.
Et „altid tændt“-mærke fra appbutikken erstatter heller ikke den kontrakt. Altid tændt og låsning er enhedsindstillinger, ofte anvendt af en enhedsejer, og deres adfærd for udeladte apps defineres af platformen. Læs indstillingen, ikke badgen.
Fire spørgsmål til en designgennemgang
For det første, hvem samtykkede: hvilken pakke, hvilken profil, og var det brugeren eller en politik for administrerede enheder? For det andet, hvad anmodede appen om: hvilke ruter, hvilke adressefamilier, hvilke medtagne eller udeladte apps? For det tredje, hvad sker der, når tunnelen ikke er tilgængelig: blokerer systemet, eller falder trafikken tilbage til det underliggende netværk? For det fjerde, hvad gør appen med de pakker, den modtager?
Det fjerde spørgsmål er det, tilladelsesmodellen ikke kan besvare. Samtykke og en TUN-grænseflade beviser, at appen kan modtage trafik, ikke at den krypterer den, autentificerer en modpart eller genopretter sig rent. Det er implementeringsegenskaber, og det er der, en ærlig gennemgang bruger sin tid.
En unødvendig root-anmodning bliver ikke legitim af at kalde resultatet en kill switch, og en samtykkedialog er ikke en sikkerhedsrevision. Hold de tre tilladelser adskilt, og hver påstand bliver kontrollerbar.