VpnService protect() eller app-utestenging: kva som rettar opp ruttinga
Vern socketen som ber tunnelen, eller steng heile appen ute: dei tre vilkåra som avgjer kva omfang Android-VPN-en din treng.
Du har to måtar å halde dei eigne pakka til tunnelen utanfor tunnelen: verne transportsocketen, eller ta heile appen ut av VPN-en. Dei løyser ulike problem, og å velje den vidare fordi han er lettare å kople opp, er nettopp måten apper mistar tilgang til det lokale nettet og delt DNS utan å merke det. Start med det som må bli utanfor tunnelen, og vel så det minste omfanget som oppnår det.
Kva protect() fjernar frå tunnelen
VpnService.protect() er eit kall per socket. Du gir han socketen eller deskriptoren som ber tunnelen, og Android merkar socketen slik at trafikken brukar det underliggande nettet i staden for VPN-grensesnittet. Alt anna appen sender, følgjer framleis den vanlege VPN-ruta.
Nettopp dette smale omfanget er poenget. Ein verna socket endrar ikkje korleis HTTP-klienten din slår opp namn, kva grensesnitt analysekalla dine brukar, eller kva som skjer med ei andre tilkopling som blir opna seinare.
Tre vilkår som avgjer omfanget
Det første vilkåret er om berre tunneltransporten må sleppe ut. Viss den øvrige trafikken til appen framleis skal gå gjennom VPN-en, er socketvern rett omfang. Det andre vilkåret er om du styrer opprettinga av socketen. Eit bibliotek som opnar sin eigen socket djupt inne, gir deg ingen stad å kalle protect(), med mindre det eksponerer ein hook eller godtek ein ferdigbygd socket. Det tredje vilkåret er om appen må nå det lokale nettet eller ein captive portal direkte, noko som er eit anna krav enn å halde tunnelen levande.
Å stengje ute appen med addDisallowedApplication() er det grove verktøyet. Det fjernar kvar tilkopling appen gjer frå VPN-en, òg dei du ville inspisere, og på nokre einingar endrar det òg korleis lokal oppdaging oppfører seg.
Eit tredje alternativ er å binde transporten til eit valt nettverk med bindProcessToNetwork() eller eit nettverkshandtak på socketnivå. Det er nyttig når eininga har Wi-Fi og mobil samtidig og du vil at tunnelen skal gå over ei bestemd oppstraumslenke.
Kall det medan transporten blir oppretta
Kall protect() i same blokka som opprettar transporten, før connect() eller send(). Viss kallet returnerer false, lukk socketen og la oppsettet feile; å halde fram lèt deg sitje att med ein transport der pakka kan kome tilbake i ditt eige grensesnitt.
Formen er liten nok til å haldast på ein stad:
DatagramSocket transport = new DatagramSocket();
if (!protect(transport)) {
transport.close();
throw new IOException("transport not protected");
}
transport.connect(serverAddress);Tre detaljar bit her. For det første,booleanen er det einaste signalet du får, så logg feilen med nok kontekst til å skilje eit tilbakekalla samtykke frå eit avvist kall. For det andre,protect() dekkjer socketen, ikkje deskriptornummeret: viss du lukkar socketen og seinare brukar same heiltal for ein annan socket, er den nye socketen ikkje verna. For det tredje, når eit nativt bibliotek opnar transporten, vern deskriptoren før den native koden koplar til, elles kan ruta alt vere vald.VpnService-referansen er staden der du stadfester kva overlastingar mål-API-nivået ditt faktisk tilbyr.
Test den blokkerte vegen, ikkje berre den glade
Stadfest med tunnelen oppe, fordi det er den einaste tilstanden der dei to vegane kan skilje seg. Send éin førespurnad gjennom den verna transporten og éin frå ein kodeveg som aldri kalla protect(), og samanlikn så kva den fjerne enden ser: den verna tilkoplinga skal kome med det underliggande nettet som kjelde, medan den uverna viser den eigne adressa til tunnelen og flyttar bytteteljarane hans. På eininga viser ss eller netstat den same delinga før noko forlèt radioen.
Test tilbakekallinga separat, fordi ei endring i samtykke riv ned grensesnittet utan å røre socketkoden din. Kalla tilbake VPN-samtykket eller stopp tenesta, bygg transporten på nytt, og stadfest at protect() framleis returnerer true og at transporten koplar til att så snart samtykket blir gitt på nytt.
Viss den verna førespurnaden likevel følgjer tunnelen, skjer vernkallet truleg etter at socketen alt er ruta. Flytt det tidlegare og test på nytt.
Hald avgjerda skriven ned ved sida av transportoppsettet: kva sockets som er verna, kva apptrafikk som er stengd ute, og kva appen gjer når vernet sviktar. Nettopp den linja hindrar ein seinare refaktor i å utvide utestenginga til heile appen fordi éin test feila. Ho gir òg neste person ein måte å sjekke intensjonen på utan å reversere manifestet.