VpnService protect() vai lietotnes izslēgšana: kas salabo maršrutēšanu
Aizsargājiet tuneli nesošo socket vai izslēdziet visu lietotni: trīs nosacījumi, kas nosaka, kāds tvērums nepieciešams jūsu Android VPN.
Ir divi veidi, kā turēt tuneļa pašu paketes ārpus tuneļa: aizsargāt transporta socket vai izņemt visu lietotni no VPN. Tie risina dažādas problēmas, un platākā izvēle tāpēc, ka to ir vieglāk pievienot, ir tieši tas ceļš, kurā lietotnes bez pamanīšanas zaudē piekļuvi vietējam tīklam un sadalīto DNS. Sāciet ar to, kam jāpaliek ārpus tuneļa, un tad izvēlieties mazāko tvērumu, kas to panāk.
Ko protect() izņem no tuneļa
VpnService.protect() ir izsaukums vienam socket. Jūs tam nododat tuneli nesošo socket vai deskriptoru, un Android atzīmē šo socket, lai tā trafiks izmantotu apakšējo tīklu, nevis VPN saskarni. Viss pārējais, ko lietotne sūta, joprojām iet parasto VPN maršrutu.
Tieši šis šaurais tvērums ir būtība. Aizsargāts socket nemaina to, kā jūsu HTTP klients atrisina vārdus, kuru saskarni izmanto jūsu analītikas izsaukumi vai kas notiek ar otru savienojumu, kas atvērts vēlāk.
Trīs nosacījumi, kas nosaka tvērumu
Pirmais nosacījums ir, vai ārā jāiet tikai tuneļa transportam. Ja pārējam lietotnes trafikam joprojām jāiet caur VPN, socket aizsardzība ir pareizais tvērums. Otrais nosacījums ir, vai jūs kontrolējat socket izveidi. Bibliotēka, kas atver savu socket dziļi iekšā, neatstāj vietu, kur izsaukt protect(), ja vien tā nepiedāvā hook vai nepieņem gatavu socket. Trešais nosacījums ir, vai lietotnei tieši jāsasniedz vietējais tīkls vai captive portal, kas ir cita prasība nekā tuneļa uzturēšana dzīvu.
Lietotnes izslēgšana ar addDisallowedApplication() ir rupjš instruments. Tas izņem no VPN katru lietotnes izveidoto savienojumu, tostarp tos, ko gribējāt pārbaudīt, un dažās ierīcēs maina arī vietējās atklāšanas uzvedību.
Trešā iespēja ir piesaistīt transportu izvēlētam tīklam ar bindProcessToNetwork() vai tīkla rokturi socket līmenī. Tas noder, ja ierīcei vienlaikus ir Wi-Fi un mobilais tīkls un vēlaties, lai tunelis ietu pa noteiktu augšupielādes kanālu.
Izsauciet to, kamēr transports tiek veidots
Izsauciet protect() tajā pašā blokā, kas veido transportu, pirms connect() vai send(). Ja izsaukums atgriež false, aizveriet socket un lieciet iestatīšanai neizdoties; turpinot paliek transports, kura paketes var atkal iekļūt jūsu pašu saskarnē.
Forma ir pietiekami maza, lai to turētu vienā vietā:
DatagramSocket transport = new DatagramSocket();
if (!protect(transport)) {
transport.close();
throw new IOException("transport not protected");
}
transport.connect(serverAddress);Šeit koda trīs detaļas. Pirmkārt,būla vērtība ir vienīgais signāls, ko saņemat, tāpēc reģistrējiet neveiksmi ar pietiekamu kontekstu, lai atšķirtu atsauktu piekrišanu no noraidīta izsaukuma. Otrkārt,protect() aptver socket, nevis deskriptora numuru: ja aizverat socket un vēlāk to pašu veselo skaitli izmantojat citam socket, jaunais socket nav aizsargāts. Treškārt, kad native bibliotēka atver transportu, aizsargājiet deskriptoru pirms native koda pievienošanās, citādi maršruts var būt jau izvēlēts.VpnService uzziņa ir vieta, kur apstiprināt, kuras pārslodzes jūsu mērķa API līmenis patiešām nodrošina.
Pārbaudiet bloķēto ceļu, ne tikai laimīgo
Pārbaudiet ar paceltu tuneli, jo tā ir vienīgā stāvoklis, kurā divi ceļi var atšķirties. Nosūtiet vienu pieprasījumu pa aizsargāto transportu un vienu no koda ceļa, kas nekad nav izsaucis protect(), pēc tam salīdziniet, ko redz tālais gals: aizsargātajam savienojumam jāierodas ar apakšējo tīklu kā avotu, bet neaizsargātais rāda paša tuneļa adresi un kustina tuneļa baitu skaitītājus. Ierīcē ss vai netstat rāda to pašu sadalījumu, pirms kaut kas iziet no radio.
Atsaukšanu pārbaudiet atsevišķi, jo piekrišanas maiņa nojauc saskarni, neaizskarot jūsu socket kodu. Atsauciet VPN piekrišanu vai apturiet pakalpojumu, izveidojiet transportu no jauna un apstipriniet, ka protect() joprojām atgriež true un transports atkal pievienojas, tiklīdz piekrišana tiek dota vēlreiz.
Ja aizsargātais pieprasījums tomēr seko tunelim, aizsardzības izsaukums, iespējams, notiek pēc tam, kad socket jau ir maršrutēts. Pārvietojiet to agrāk un pārbaudiet vēlreiz.
Turiet lēmumu pierakstītu blakus transporta iestatījumam: kuri socket ir aizsargāti, kurš lietotnes trafiks ir izslēgts un ko lietotne dara, kad aizsardzība neizdodas. Tieši šī rinda neļauj vēlākai pārstrukturēšanai paplašināt izslēgšanu uz visu lietotni tāpēc, ka viens tests neizdevās. Tā arī dod nākamajam cilvēkam veidu, kā pārbaudīt nodomu, neveicot manifesta reverso inženieriju.