Hindi, hindi kayang buksan ng isang VpnService app ang VPN ng telepono
Pagmamay-ari ng app ang isang tunel at ang lifecycle nito, hindi ang switch ng VPN ng telepono. Maaaring bawiin ang pahintulot, isang VPN lang ang tumatakbo sa isang pagkakataon, at ang mga packet ay sa iyo upang suriin.
Ang maling palagay ay ang VpnService app ay nagbabaligtad ng switch ng system at mula noon ay protektado na ang telepono. Ang talagang nangyayari ay mas makitid: humihingi ng pahintulot ang app, gumagawa ng interface, nagbabasa at nagsusulat ng mga packet sa pamamagitan ng file descriptor, at ibinabalik ang interface kapag huminto ito. Isang ganoong tunel lang ang maaaring mabuhay sa isang pagkakataon, at maaaring kunin ito ng system nang hindi nagtatanong. Karamihan ng nakalilitong pag-uugali na ibinabato ng mga tao sa protocol ay nagmumula sa modelong iyon ng pagmamay-ari.
Ituring ang bawat paglipat ng lifecycle bilang bahagi ng disenyo at hindi bilang dulong kaso.
Mito: binubuksan ng app ang VPN ng telepono
Nagsisimula ang daloy sa VpnService.prepare(), na nagbabalik ng Intent na dapat tanggapin ng user, at nagpapatuloy sa establish(), na maaari pa ring mabigo pagkatapos dahil sa mga dahilan na hindi kontrolado ng app. Ang pagtatatag ng pangalawang tunel ay nagpapawalang-bisa sa unang interface at pumapalit sa notification ng system. Wala kahit saan sa pagkakasunod-sunod na iyon na pagmamay-ari ng app ang isang switch para sa buong device; pagmamay-ari nito ang descriptor na ibinigay dito at ang mga packet na dumarating doon. Kahit ang tuloy-tuloy na notification ay pagmamay-ari ng system at hindi ng disenyo ng app.
Dahil ibinibigay ang interface at hindi sinasamsam, maaaring kunin ng ibang client ang puwesto anumang oras. Natututuhan ito ng app sa pamamagitan ng callback, hindi sa pamamagitan ng return value.
Nakikita ang sapilitang paghinto ng app sa panel ng notification sa parehong dahilan: iniuulat ng system ang ibinigay nito, hindi ang pinili ng app na ipakita.
Mito: ibinibigay ang pahintulot nang isang beses
Kapag ipinasa ng system ang tunel sa ibang client, nagpapadala ito ng transaksyon ng pagbawi sa binder na ibinabalik ng base class mula sa onBind(). Ang app na pumapalit sa binder na iyon ng sarili nito ay dapat mismo magpasa ng transaksyon ng pagbawi, kung hindi ay hindi kailanman mag-trigger ang VpnService.onRevoke() at patuloy na magsusulat ang serbisyo sa descriptor na wala na. Maaari ring bawiin ng user ang pag-apruba, at maaaring ihinto ng system ang serbisyo habang nag-restart o nagre-reconnect na laging naka-on.
Ang paghawak dito ay kongkretong trabaho at hindi isang linya ng log: itigil ang pagbasa sa descriptor, isara ito, i-clear ang flag ng konektado at sabihin sa user kung anong estado siya. Pagkatapos ay magpasya kung dapat magtatag muli ang app, magtanong muli o maghintay, dahil sa isang laging naka-on na configuration ay maaaring ibalik ng system ang serbisyo nang mag-isa.
Ang app na itinuturing ang pagbawi bilang eksepsiyon at hindi bilang estado ay mag-uulat na konektado habang ang bawat packet na isinusulat nito ay itinatapon, at iyon ang pinakamasamang mode ng pagkabigo para sa isang kasangkapan sa privacy.
Mito: sinasala ng interface ang trapiko para sa iyo
Ang dumarating ay hilaw na IP. Ang paghuli o pagsala ay nangangahulugan ng pagsusuri sa mga header ng IP, TCP, UDP at IPv6, pagsubaybay sa mga daloy at pagsulat ng mga tugon pabalik sa descriptor, na ginagawang maliit na stack ng network ang isang app sa paghuli at hindi isang pasilidad ng system. Umiiral ang protect() upang ang sariling transport socket ng app ay lumihis sa tunel nito sa halip na hulihin ang sarili nito, at nagbabalik ito ng boolean na karapat-dapat suriin sa bawat socket na ginawa pagkatapos ng tunel.
Ang mga listahan ng pinapayagan at ipinagbabawal na app sa builder ang nagtatakda kung kaninong trapiko ang pumapasok sa interface. Hindi sila nagbibigay ng access sa payload na lampas sa mga IP packet na dinadala ng interface, at walang API na naglalantad ng tunel ng ibang client o naglilista ng mga profile ng VPN ng system. Maaaring sabihin ng mga kakayahan ng network na ang isang network ay transport ng VPN, ngunit hindi kung kanino ang tunel.
Kaya ang mga tanong tungkol sa estado ng ibang app ay nakakakuha ng magkasalungat na sagot: ang impormasyon ay hindi lang talaga inilalantad sa iyong proseso.
Ano ang talagang hinihingi ng lifecycle
Subaybayan ang mga estadong kontrolado mo: handa, naitatag, nabawi, nahinto. Ang muling pagkonekta ay dapat na pagtanggal at pagkatapos ay pagtatatag, na may isang may-ari ng descriptor at ng transport socket, dahil ang dalawang bahagi na nag-uunahan na magtatag ay mag-aaway para sa nag-iisang bakanteng puwesto. Ang mga pagsisimula sa background ay limitado sa modernong Android, kaya ang broadcast sa boot ay hindi garantiya; gumamit ng foreground service kasama ang notification nito kung saan pinapayagan ng antas ng API.
I-log ang paglipat at hindi lang ang huling estado, at panatilihing sapat na maliit ang state machine upang subukan ang bawat landas. Ang estadong hindi mo maabot sa pagsubok ay estadong makakaharap mo sa field na walang log.
Subukan ang lifecycle sa isang device
Kayang pekein ng mga emulator ang konektibidad ngunit hindi ang landas ng pahintulot at pagbawi nang nakakumbinsi, kaya patakbuhin ang mga ito sa isang tunay na device na may naka-install na pangalawang VPN client upang nakawin ang puwesto.
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
Simulan ang tunel, kumpirmahin ang notification at interface, pagkatapos ikonekta ang isa pang client at panoorin kung tumatakbo ang callback ng pagbawi at kung nalilinis ang estado. Sapilitang ihinto ang app at tingnan kung may nag-uulat pa ng buhay na descriptor.
Ulitin ang pagkakasunod-sunod pagkatapos ng laging naka-on na restart, dahil iba ang landas na iyon sa koneksyong sinimulan ng user. Hindi berdeng icon ang hinahanap mo kundi patunay na tumigil ang app sa paggamit ng descriptor na hindi na pagmamay-ari nito.