Tunel i ndarë në Android VpnService: çfarë mund të rrugëzoni vërtet
VpnService përcjell vetëm paketat që builder vendos në përshkruesin e vet. Kontrollo parashtesat, vërtetimin e proxy-t, DNS-në dhe listat e aplikacioneve përpara se të fajësosh tunelin e ndarë.
Tuneli i ndarë në një aplikacion VpnService thyhet në disa pika konkrete, dhe riparimi është i ndryshëm për secilën. Klienti shfaq vetëm një destinacion që dështon, prandaj puna e parë është të zbulosh cilën kufi po godet: rrugët që mori builder, proxy-ja që nuk mund ta vërtetosh, resolver-i që vetëm e shpalle, ose lista e aplikacioneve që platforma e zbaton për çdo përdorues. Pikërisht për këtë mbaj një kontroll në katër hapa. Ai ecën sipas rendit më poshtë dhe ndalon në dështimin e parë.
Konfirmo çfarë i dha builder platformës
VpnService.Builder është një listë deklaratash. establish() kthen një ParcelFileDescriptor për një ndërfaqe virtuale, dhe platforma dërgon në atë përshkrues vetëm trafikun që përputhet me parashtesat e addAddress dhe addRoute; addDnsServer u thotë klientëve cilin resolver të pyesin. Një destinacion jashtë të gjitha parashtesave që shtove nuk arrin kurrë në aplikacionin tënd, çfarëdo që premton ndërfaqja. Ky fakt i vetëm shpjegon shumicën e raportimeve për tunel të ndarë të prishur edhe para se të ndryshohet kodi.
Regjistro listat e adresave, rrugëve dhe DNS që mblodhi builder-i yt, pastaj krahasoji me destinacionet që dështojnë. Një /32 që mungon për një host administrimi është shumë më i zakonshëm sesa një tunel i prishur. Nëse lista është e saktë, vazhdo; nëse është e gabuar, pjesa tjetër e listës së kontrollit është përpjekje e humbur.
excludeRoute ekziston vetëm nga API 33
Përjashtimi i bazuar në destinacion është kërkesa që më shpesh përfundon si një temë mbështetjeje. builder.excludeRoute(IpPrefix) erdhi në API 33; përpara kësaj, përafrimi i vetëm i mbështetur është të shtohen rrugë për gjithçka përveç parashtesës së përjashtuar, që do të thotë t'i llogaritësh vetë parashtesat plotësuese. Të dy thirrjet nuk janë imazhe pasqyre: njëra zbret nga grupi i rrugëve të ndërfaqes, tjetra e ndërton grupin nga zeroja, dhe një pajisje më e vjetër do të hedhë ose do të injorojë në heshtje një thirrje që nuk e njeh. Degëzo sipas Build.VERSION.SDK_INT dhe provo të dyja rrugët në harduer të vërtetë.
Kur llogarit plotësuesit, kihe kujdes përafrimin e parashtesave. Një përjashtim /24 brenda një rruge /16 kërkon parashtesat mbuluese që përshkruajnë vërtet pjesën e mbetur, jo një /8 të deformuar. Regjistro listën përfundimtare dhe verifiko që hosti i përjashtuar ende zgjidhet përmes një rruge jashtë tunelit.
Kredencialet e proxy-t nuk mund të shprehen
setHttpProxy(ProxyInfo) e drejton ndërfaqen te një proxy HTTP ose SOCKS, dhe një URL PAC mund të zgjedhë mes tyre për çdo destinacion. As ProxyInfo as formati PAC nuk bartin emrin e përdoruesit dhe fjalëkalimin, prandaj një proxy që kërkon vërtetim mbetet jashtë API-t të platformës. Aplikacionet që kanë nevojë për të zakonisht përfshijnë një stivë të hapësirës së përdoruesit, tun2socks ose një motor të ngjashëm, dhe i përgjigjen vetë sfidës 407.
Kjo zgjedhje ka pasoja. Një stivë e hapësirës së përdoruesit sheh vetëm trafikun që rrugëzon drejt saj, prandaj duhet të jetë brenda të njëjtit kufi përshkruesi, dhe trashëgon të njëjtën kërkesë protect() për socket-in e vet të lidhjes lart. Nëse e lë protect() jashtë, tuneli kap transportin e vet, gjë që shfaqet si një shtrëngim duarsh që ngec pas paketës së parë. Provo kundër një proxy që kërkon kredenciale, sepse një proxy e hapur kalon në rrugën e platformës dhe nuk provon asgjë.
Listat për aplikacion dhe DNS janë gjithashtu deklarata
Builder ka addAllowedApplication dhe addDisallowedApplication, dhe ato përjashtojnë njëri-tjetrin: thirrja e të dyjave hedh përjashtim. Në çdo rast lista zbatohet për çdo përdorues kur konfigurohet ndërfaqja, prandaj një aplikacion i profilit të punës udhëhiqet nga tuneli i profilit të punës dhe jo nga yti. Ajo që asnjë API nuk të jep është kontrolli mbi vendimin e një aplikacioni tjetër: nuk mund të shtysh një paketë në tunelin tënd nga jashtë dhe nuk mund të mbyllësh ose rikonfigurosh një VPN tashmë aktive.
DNS ndjek të njëjtin model. addDnsServer shpall një adresë resolver-i; nuk lejon aplikacionin tënd të përgjigjet për kërkesat. Nëse do t'i zgjidhësh vetë emrat, ekzekuto një resolver dhe rrugëzo adresën e tij në tunel. Aplikacionet që përdorin DoT ose DoH drejt një emri hosti fiks mund të anashkalojnë adresën që shpalle, prandaj trajto zgjidhjen e emrave si përpjekje më e mirë, përveçse nëse intercepton edhe rrugën e kërkesës.
Manifest, always-on dhe testi në katër hapa
Përshtatshmëria deklarohet në manifest: BIND_VPN_SERVICE, filtri i intent-it android.net.VpnService dhe një shërbim në plan të parë nëse tuneli duhet të mbijetojë në sfond. Always-on VPN kërkon gjithashtu një onRevoke të pastër, sepse sistemi e thërret kur përdoruesi ndryshon cilësimet ose një aplikacion tjetër merr kontrollin.
Kryej kontrollat sipas radhës dhe ndalo në dështimin e parë. Së pari, nxirr listat e adresave, rrugëve dhe DNS që iu dhanë builder-it. Së dyti, konfirmo që establish() ktheu një përshkrues dhe se socket-i i transportit është i mbrojtur. Së treti, kërko një destinacion brenda një parashtese të përfshirë dhe një brenda një parashtese të përjashtuar. Së katërti, kontrollo cili resolver u përgjigj vërtet duke pyetur një emër hosti që vetëm resolver-i yt mund ta zgjidhë.
Një shtrëngim duarsh i përfunduar nuk provon asnjë nga hapat e mëvonshëm. Çdo kontroll izolon një shtresë, prandaj një sukses në hapin e dytë nuk thotë asgjë për të katërtin.
Referenca e VpnService.Builder rendit të gjithë sipërfaqen e builder-it. Çdo gjë që të duhet përtej saj është një API tjetër, një aplikacion tjetër ose stiva jote e hapësirës së përdoruesit, dhe ky është një vendim projektimi, jo një defekt i tunelit të ndarë.