Supozimi i gabuar është se një aplikacion VpnService kthen një çelës të sistemit dhe se prej andej telefoni mbrohet. Ajo që ndodh në të vërtetë është më e ngushtë: aplikacioni kërkon pëlqim, ndërton një ndërfaqe, lexon dhe shkruan paketa përmes një përshkruesi skedari, dhe e kthen ndërfaqen kur ndalon. Vetëm një tunel i tillë mund të jetë i gjallë në të njëjtën kohë, dhe sistemi mund ta marrë pa pyetur. Pjesa më e madhe e sjelljes konfuze që njerëzit ia hedhin protokollit vjen nga ai model pronësie.

Trajtojeni çdo tranzicion të ciklit të jetës si pjesë të projektimit dhe jo si rast kufitar.

Miti: aplikacioni ndez VPN-në e telefonit

Rrjedha fillon me VpnService.prepare(), i cili kthen një Intent që përdoruesi duhet ta pranojë, dhe vazhdon me establish(), i cili më pas mund të dështojë ende për arsye që aplikacioni nuk i kontrollon. Vendosja e një tuneli të dytë çaktivizon ndërfaqen e parë dhe zëvendëson njoftimin e sistemit. Askund në atë sekuencë aplikacioni nuk zotëron një çelës për të gjithë pajisjen; zotëron përshkruesin që iu dha dhe paketat që ulen mbi të. Edhe njoftimi i përhershëm i takon sistemit dhe jo projektimit të aplikacionit.

Meqenëse ndërfaqja jepet dhe nuk rrëmbehet, një klient tjetër mund ta zërë vendin në çdo moment. Aplikacioni e mëson këtë përmes një thirrjeje kthimi, jo përmes një vlere kthimi.

Ndalimi me forcë i aplikacionit duket në panelin e njoftimeve për të njëjtën arsye: sistemi raporton atë që dha, jo atë që aplikacioni zgjodhi të shfaqë.

Miti: pëlqimi jepet një herë

Kur sistemi ia dorëzon tunelin një klienti tjetër, dërgon një transaksion tërheqjeje mbi binder-in që klasa bazë kthen nga onBind(). Një aplikacion që e zëvendëson atë binder me të vetin duhet ta përcjellë vetë transaksionin e tërheqjes, përndryshe VpnService.onRevoke() nuk aktivizohet kurrë dhe shërbimi vazhdon të shkruajë në një përshkrues që nuk ekziston më. Miratimin mund ta tërheqë edhe përdoruesi, dhe sistemi mund ta ndalojë shërbimin gjatë një rindezjeje ose një rilidhjeje gjithmonë aktive.

Trajtimi i kësaj është punë konkrete dhe jo një rresht log: ndaloni leximin e përshkruesit, mbylleni atë, pastroni flamurin e lidhjes dhe i thoni përdoruesit në çfarë gjendjeje ndodhet. Pastaj vendosni nëse aplikacioni duhet të rivendosë, të pyesë përsëri ose të presë, sepse në një konfigurim gjithmonë aktiv sistemi mund ta kthejë vetë shërbimin.

Një aplikacion që e trajton tërheqjen si përjashtim dhe jo si gjendje do të raportojë lidhje ndërsa çdo paketë që shkruan hidhet, dhe ky është mënyra më e keqe e mundshme e dështimit për një mjet privatësie.

Miti: ndërfaqja filtron trafikun në vendin tuaj

Ajo që arrin është IP e papërpunuar. Kapja ose filtrimi nënkupton analizimin e titujve IP, TCP, UDP dhe IPv6, ndjekjen e rrjedhave dhe shkrimin e përgjigjeve përsëri në përshkrues, gjë që e kthen një aplikacion kapjeje në një stivë të vogël rrjeti dhe jo në një lehtësi të sistemit. protect() ekziston që vetë socket-i i transportit i aplikacionit të anashkalojë tunelin e tij në vend që të kapë veten, dhe kthen një vlerë boolean që meriton një kontroll në çdo socket të krijuar pasi tuneli është lart.

Listat e aplikacioneve të lejuara dhe të ndaluara në ndërtues vendosin se kush e fut trafikun në ndërfaqe. Ato nuk japin akses në ngarkesën përtej paketave IP që mbart ndërfaqja, dhe asnjë API nuk zbulon tunelin e një klienti tjetër as rendit profilet VPN të sistemit. Aftësitë e rrjetit mund të thonë se një rrjet është transport VPN, por jo e kujt është tuneli.

Për këtë arsye pyetjet për gjendjen e aplikacioneve të tjera marrin përgjigje kontradiktore: informacioni thjesht nuk i ekspozohet procesit tuaj.

Çfarë kërkon vërtet cikli i jetës

Ndiqni gjendjet që kontrolloni: përgatitur, vendosur, tërhequr, ndalur. Rilidhja duhet të jetë çmontim i ndjekur nga vendosja, me një pronar të vetëm për përshkruesin dhe socket-in e transportit, sepse dy komponentë që garojnë për të vendosur do të përleshen për vendin e vetëm të lirë. Nisjet në sfond janë të kufizuara në Android-in modern, prandaj një transmetim në nisje nuk është garanci; përdorni një shërbim në plan të parë me njoftimin e tij aty ku niveli i API-së e lejon.

Regjistroni tranzicionin dhe jo vetëm gjendjen përfundimtare, dhe mbajeni makinën e gjendjeve mjaft të vogël për të provuar çdo rrugë. Një gjendje që nuk mund ta arrini në një provë është një gjendje që do ta takoni në terren pa log.

Provoni ciklin e jetës në një pajisje

Emulatorët mund të falsifikojnë lidhshmërinë por jo rrugën e pëlqimit dhe të tërheqjes në mënyrë bindëse, prandaj ekzekutojini këto në një pajisje reale me një klient të dytë VPN të instaluar që ta vjedhë vendin.

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

Nisni tunelin, konfirmoni njoftimin dhe ndërfaqen, pastaj lidhni klientin tjetër dhe vëzhgoni nëse thirrja e kthimit e tërheqjes ekzekutohet dhe nëse gjendja pastrohet. Ndalojeni aplikacionin me forcë dhe kontrolloni nëse diçka raporton ende një përshkrues të gjallë.

Përsëriteni sekuencën pas një rindezjeje gjithmonë aktive, sepse ajo rrugë ndryshon nga një lidhje e nisur nga përdoruesi. Ajo që kërkoni nuk është një ikonë e gjelbër por prova se aplikacioni ndaloi së përdoruri një përshkrues që nuk e zotëronte më.

Artikuj të ngjashëm