Ne, VpnService-a aplikaĵo ne povas ŝalti la VPN de la telefono
La aplikaĵo posedas unu tunelon kaj ĝian vivciklon, ne la ŝaltilon de la telefono. Konsento povas esti revokita, nur unu VPN funkcias samtempe, kaj la pakaĵojn vi mem analizu.
La erara supozo estas, ke VpnService-a aplikaĵo turnas sisteman ŝaltilon kaj de tiam la telefono estas protektita. Kio efektive okazas estas pli mallarĝa: la aplikaĵo petas konsenton, konstruas interfacon, legas kaj skribas pakaĵojn tra dosierpriskribilo, kaj redonas la interfacon kiam ĝi haltas. Nur unu tia tunelo povas vivi samtempe, kaj la sistemo povas forpreni ĝin sen demandi. La plej granda parto de la konfuza konduto, kiun homoj kulpigas la protokolon, venas el tiu posedmodelo.
Traktu ĉiun transiron de la vivciklo kiel parton de la dezajno, ne kiel randan kazon.
Mito: la aplikaĵo ŝaltas la VPN de la telefono
La fluo komenciĝas per VpnService.prepare(), kiu redonas Intent, kiun la uzanto devas akcepti, kaj daŭras per establish(), kiu poste ankoraŭ povas malsukcesi pro kialoj, kiujn la aplikaĵo ne regas. Starigo de dua tunelo malŝaltas la unuan interfacon kaj anstataŭigas la sistemkonsciigon. Nenie en tiu sinsekvo la aplikaĵo posedas ŝaltilon por la tuta aparato; ĝi posedas la priskribilon, kiun oni donis al ĝi, kaj la pakaĵojn, kiuj surteriĝas sur ĝin. Eĉ la daŭra konsciigo apartenas al la sistemo, ne al la dezajno de la aplikaĵo.
Ĉar la interfaco estas donata, ne kaptata, alia kliento povas okupi la lokon iam ajn. La aplikaĵo ekscias tion per revokaĵo, ne per revena valoro.
Trudhalto de la aplikaĵo videblas en la konsciiga panelo pro la sama kialo: la sistemo raportas, kion ĝi donis, ne kion la aplikaĵo elektis montri.
Mito: konsento estas donata unufoje
Kiam la sistemo transdonas la tunelon al alia kliento, ĝi sendas revokan transakcion sur la binder, kiun la baza klaso redonas el onBind(). Aplikaĵo, kiu anstataŭigas tiun binder per sia propra, devas mem plusendi la revokan transakcion, alie VpnService.onRevoke() neniam ekfunkcias kaj la servo daŭre skribas en priskribilon, kiu jam ne ekzistas. La aprobon povas revoki ankaŭ la uzanto, kaj la sistemo povas haltigi la servon dum restarigo aŭ dum ĉiama rekonekto.
Prizorgi tion estas konkreta laboro, ne loglinio: ĉesu legi la priskribilon, fermu ĝin, viŝu la konektitan flagon kaj diru al la uzanto, en kiu stato li estas. Poste decidu, ĉu la aplikaĵo restarigu, demandu denove aŭ atendu, ĉar en ĉiama agordo la sistemo povas mem revenigi la servon.
Aplikaĵo, kiu traktas revokon kiel escepton anstataŭ kiel staton, raportos konektite dum ĉiu pakaĵo, kiun ĝi skribas, estas forĵetata, kio estas la plej malbona ebla fiaskmaniero por privateca ilo.
Mito: la interfaco filtras trafikon por vi
Kio alvenas estas kruda IP. Kapti aŭ filtri signifas analizi IP-, TCP-, UDP- kaj IPv6-kapojn, spuri fluojn kaj skribi respondojn reen al la priskribilo, kio faras kaptan aplikaĵon malgranda retstako anstataŭ sistema instalaĵo. protect() ekzistas por ke la propra transporta ingo de la aplikaĵo preterpasu sian tunelon anstataŭ kapti sin mem, kaj ĝi redonas bulean valoron, kiu meritas kontrolon ĉe ĉiu ingo kreita post kiam la tunelo estas supre.
La listoj de permesitaj kaj malpermesitaj aplikaĵoj en la konstruilo decidas, kies trafiko eniras la interfacon. Ili ne donas aliron al utilŝarĝo preter la IP-pakaĵoj, kiujn la interfaco portas, kaj neniu API malkaŝas la tunelon de alia kliento nek listigas la VPN-profilojn de la sistemo. Retaj kapabloj povas diri, ke reto estas VPN-transporto, sed ne kies tunelo ĝi estas.
Tial statusaj demandoj pri aliaj aplikaĵoj ricevas kontraŭdirajn respondojn: la informo simple ne estas malkaŝita al via procezo.
Kion la vivciklo efektive postulas
Spuru la statojn, kiujn vi regas: preta, starigita, revokita, haltigita. Rekonekto devus esti malkonstruo sekvata de starigo, kun unu posedanto de la priskribilo kaj la transporta ingo, ĉar du komponantoj, kiuj konkurse starigas, batalos pri la ununura disponebla loko. Fonaj startoj estas limigitaj en moderna Android, do dissendaĵo ĉe ŝaltiĝo ne estas garantio; uzu antaŭplanan servon kun ĝia konsciigo, kie la API-nivelo permesas.
Registru la transiron, ne nur la finan staton, kaj tenu la statmaŝinon sufiĉe malgranda por testi ĉiun vojon. Stato, kiun vi ne povas atingi en testo, estas stato, kiun vi renkontos sur la kampo sen registro.
Testu la vivciklon sur aparato
Emuliloj povas ŝajnigi konektecon sed ne konvinke la vojon de konsento kaj revoko, do rulu ĉi tiujn sur reala aparato kun dua VPN-kliento instalita por ŝteli la lokon.
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
Startigu la tunelon, konfirmu la konsciigon kaj la interfacon, poste konektu la alian klienton kaj observu, ĉu la revoka revokilo funkcias kaj ĉu la stato puriĝas. Trudhaltigu la aplikaĵon kaj kontrolu, ĉu io ankoraŭ raportas vivan priskribilon.
Ripetu la sinsekvon post ĉiama restarigo, ĉar tiu vojo diferencas de uzant-iniciatita konekto. Kion vi serĉas ne estas verda ikono sed pruvo, ke la aplikaĵo ĉesis uzi priskribilon, kiun ĝi jam ne posedis.