Kļūdains pieņēmums ir, ka VpnService lietotne pārslēdz sistēmas slēdzi un no tā brīža tālrunis ir aizsargāts. Patiesībā notiekošais ir šaurāks: lietotne pieprasa piekrišanu, izveido saskarni, lasa un raksta paketes caur faila deskriptoru, un apstājoties atdod saskarni atpakaļ. Vienlaikus dzīvs var būt tikai viens šāds tunelis, un sistēma to var atņemt, neprasot. Lielākā daļa mulsinošās uzvedības, ko cilvēki piedēvē protokolam, nāk tieši no šī īpašumtiesību modeļa.

Uztveriet katru dzīves cikla pāreju kā dizaina daļu, nevis kā malas gadījumu.

Mīts: lietotne ieslēdz tālruņa VPN

Plūsma sākas ar VpnService.prepare(), kas atgriež Intent, kurš lietotājam ir jāpieņem, un turpinās ar establish(), kas pēc tam joprojām var neizdoties tādu iemeslu dēļ, kurus lietotne nekontrolē. Otra tuneļa izveide deaktivizē pirmo saskarni un aizstāj sistēmas paziņojumu. Nekur šajā secībā lietotnei nepieder visas ierīces slēdzis; tai pieder piešķirtais deskriptors un paketes, kas uz tā nonāk. Pat pastāvīgais paziņojums pieder sistēmai, nevis lietotnes dizainam.

Tā kā saskarne tiek piešķirta, nevis sagrābta, cits klients var ieņemt vietu jebkurā brīdī. Lietotne to uzzina ar atzvanu, nevis ar atgriezto vērtību.

Lietotnes piespiedu apturēšana ir redzama paziņojumu panelī tā paša iemesla dēļ: sistēma ziņo, ko tā piešķīra, nevis ko lietotne izvēlējās rādīt.

Mīts: piekrišana tiek dota vienreiz

Kad sistēma nodod tuneli citam klientam, tā sūta atsaukšanas darījumu uz binder, ko bāzes klase atgriež no onBind(). Lietotnei, kas šo binder aizstāj ar savu, pašai ir jāpārsūta atsaukšanas darījums, citādi VpnService.onRevoke() nekad neiedarbosies un pakalpojums turpinās rakstīt deskriptorā, kura vairs nav. Piekrišanu var atsaukt arī lietotājs, un sistēma var apturēt pakalpojumu restartēšanas vai vienmēr ieslēgtas atkārtotas savienošanas laikā.

Ar to rīkoties ir konkrēts darbs, nevis žurnāla rinda: pārtrauciet lasīt deskriptoru, aizveriet to, notīriet savienotās karodziņu un pasakiet lietotājam, kādā stāvoklī viņš ir. Pēc tam izlemiet, vai lietotnei jāatjauno, jājautā vēlreiz vai jāgaida, jo vienmēr ieslēgtā konfigurācijā sistēma var pati atgriezt pakalpojumu.

Lietotne, kas atsaukšanu uzskata par izņēmumu, nevis stāvokli, ziņos par savienojumu, kamēr katrs tās rakstītais pakets tiek izmests, un tas ir sliktākais iespējamais atteices režīms privātuma rīkam.

Mīts: saskarne filtrē satiksmi jūsu vietā

Tas, kas ierodas, ir neapstrādāts IP. Uztveršana vai filtrēšana nozīmē IP, TCP, UDP un IPv6 galveņu parsēšanu, plūsmu izsekošanu un atbilžu rakstīšanu atpakaļ deskriptorā, kas uztveršanas lietotni padara par mazu tīkla steku, nevis sistēmas līdzekli. protect() pastāv tāpēc, lai pašas lietotnes transporta ligzda apietu savu tuneli, nevis uztvertu sevi, un tā atgriež Būla vērtību, ko ir vērts pārbaudīt katrai ligzdai, kas izveidota pēc tuneļa pacelšanas.

Būvētāja atļauto un aizliegto lietotņu saraksti nosaka, kura satiksme nonāk saskarnē. Tie nedod piekļuvi lietderīgajai slodzei aiz saskarnes nēsātajām IP paketēm, un neviena API neatklāj cita klienta tuneli vai uzskaita sistēmas VPN profilus. Tīkla iespējas var pateikt, ka tīkls ir VPN transports, bet ne to, kuram pieder tunelis.

Tāpēc stāvokļa jautājumi par citām lietotnēm saņem pretrunīgas atbildes: informācija vienkārši nav atklāta jūsu procesam.

Ko dzīves cikls patiesībā prasa

Izsekojiet stāvokļiem, kurus kontrolējat: sagatavots, izveidots, atsaukts, apturēts. Atkārtotai savienošanai jābūt demontāžai un pēc tam izveidei, ar vienu deskriptora un transporta ligzdas īpašnieku, jo divas sastāvdaļas, kas sacenšas par izveidi, cīnīsies par vienīgo brīvo vietu. Fona palaišanas mūsdienu Android ir ierobežotas, tāpēc sāknēšanas apraide nav garantija; izmantojiet priekšplāna pakalpojumu ar tā paziņojumu tur, kur API līmenis to atļauj.

Reģistrējiet pāreju, nevis tikai galīgo stāvokli, un turiet stāvokļa mašīnu pietiekami mazu, lai pārbaudītu katru ceļu. Stāvoklis, kuru testā nevarat sasniegt, ir stāvoklis, ar kuru laukā saskarsities bez žurnāla.

Pārbaudiet dzīves ciklu ierīcē

Emulatori var viltot savienojamību, bet ne pārliecinoši piekrišanas un atsaukšanas ceļu, tāpēc palaidiet šos reālā ierīcē ar instalētu otru VPN klientu, kas nolaupīs vietu.

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

Palaidiet tuneli, apstipriniet paziņojumu un saskarni, pēc tam pievienojiet otru klientu un vērojiet, vai atsaukšanas atzvans darbojas un vai stāvoklis tiek notīrīts. Piespiedu kārtā apturiet lietotni un pārbaudiet, vai kaut kas joprojām ziņo par dzīvu deskriptoru.

Atkārtojiet secību pēc vienmēr ieslēgtas restartēšanas, jo šis ceļš atšķiras no lietotāja uzsākta savienojuma. Jūs meklējat nevis zaļu ikonu, bet pierādījumu, ka lietotne pārtrauca izmantot deskriptoru, kas tai vairs nepiederēja.

Saistītie raksti