VpnService protect() aŭ ekskludo de la aplikaĵo: kio riparas la enkursigon
Protektu la soketon, kiu portas la tunelon, aŭ ekskludu la tutan aplikaĵon: la tri kondiĉoj, kiuj decidas, kiun amplekson via Android-VPN bezonas.
Vi havas du manierojn teni la proprajn pakaĵojn de la tunelo ekster la tunelo: protekti la transportan soketon, aŭ eligi la tutan aplikaĵon el la VPN. Ili solvas malsamajn problemojn, kaj elekti la pli vastan ĉar ĝi estas pli facile konektebla estas ĝuste tiel, kiel aplikaĵoj perdas aliron al la loka reto kaj dividitan DNS sen rimarki. Komencu de tio, kio devas resti ekster la tunelo, poste elektu la plej malgrandan amplekson, kiu tion atingas.
Kion protect() forigas el la tunelo
VpnService.protect() estas alvoko por unu soketo. Vi donas al ĝi la soketon aŭ priskribilon, kiu portas la tunelon, kaj Android markas tiun soketon tiel, ke ĝia trafiko uzu la suban reton anstataŭ la VPN-interfacon. Ĉio alia, kion la aplikaĵo sendas, daŭre sekvas la normalan VPN-vojon.
Ĝuste tiu mallarĝa amplekso estas la celo. Protektita soketo ne ŝanĝas kiel via HTTP-kliento solvas nomojn, kiun interfacon viaj analizaj alvokoj uzas, aŭ kio okazas al dua konekto malfermita poste.
Tri kondiĉoj, kiuj decidas la amplekson
La unua kondiĉo estas ĉu nur la tunela transporto devas eskapi. Se la cetera trafiko de la aplikaĵo ankoraŭ iru tra la VPN, soketa protekto estas la ĝusta amplekso. La dua kondiĉo estas ĉu vi regas la kreon de la soketo. Biblioteko, kiu malfermas sian propran soketon profunde interne, lasas al vi neniun lokon por alvoki protect() krom se ĝi montras hokon aŭ akceptas pretan soketon. La tria kondiĉo estas ĉu la aplikaĵo devas rekte atingi la lokan reton aŭ captive portal, kio estas malsama postulo ol teni la tunelon viva.
Ekskludi la aplikaĵon per addDisallowedApplication() estas la maldelikata ilo. Ĝi forigas el la VPN ĉiun konekton, kiun la aplikaĵo faras, inkluzive de tiuj, kiujn vi volis inspekti, kaj sur iuj aparatoj ĝi ankaŭ ŝanĝas kiel kondutas loka malkovro.
Tria opcio estas ligi la transporton al elektita reto per bindProcessToNetwork() aŭ reta tenilo je soketa nivelo. Tio utilas kiam la aparato havas samtempe Wi-Fi kaj poŝtelefonan reton kaj vi volas, ke la tunelo iru per difinita suprenligo.
Alvoku ĝin dum la transporto kreiĝas
Alvoku protect() en la sama bloko, kiu kreas la transporton, antaŭ connect() aŭ send(). Se la alvoko redonas false, fermu la soketon kaj malsukcesigu la agordon; daŭrigi lasas vin kun transporto, kies pakaĵoj povas reeniri vian propran interfacon.
La formo estas sufiĉe malgranda por teni ĝin en unu loko:
DatagramSocket transport = new DatagramSocket();
if (!protect(transport)) {
transport.close();
throw new IOException("transport not protected");
}
transport.connect(serverAddress);Tri detaloj mordas ĉi tie. Unue,la bulea valoro estas la sola signalo, kiun vi ricevas, do protokolu la malsukceson kun sufiĉa kunteksto por distingi revokitan konsenton de rifuzita alvoko. Due,protect() kovras la soketon, ne la priskribilan numeron: se vi fermas la soketon kaj poste reuzas la saman entjeron por alia soketo, la nova soketo ne estas protektita. Trie, kiam indiĝena biblioteko malfermas la transporton, protektu la priskribilon antaŭ ol la indiĝena kodo konektiĝas, alie la vojo eble jam estas elektita.La VpnService-referenco estas la loko, kie vi konfirmas, kiujn troŝarĝojn via cela API-nivelo efektive provizas.
Testu la blokitan vojon, ne nur la feliĉan
Kontrolu kun la tunelo supren, ĉar tio estas la sola stato, en kiu la du vojoj povas malsami. Sendu unu peton tra la protektita transporto kaj unu el koda vojo, kiu neniam alvokis protect(), poste komparu, kion vidas la malproksima fino: la protektita konekto devus alveni kun la suba reto kiel fonto, dum la neprotektita montras la propran adreson de la tunelo kaj movas ĝiajn bajtajn nombrilojn. Sur la aparato,ss aŭ netstat montras la saman dividon antaŭ ol io ajn forlasas la radion.
Testu revokadon aparte, ĉar ŝanĝo de konsento detruas la interfacon ne tuŝante vian soketan kodon. Revoku la VPN-konsenton aŭ haltigu la servon, rekonstruu la transporton, kaj konfirmu, ke protect() ankoraŭ redonas true kaj ke la transporto rekonektiĝas tuj kiam la konsento denove estas donita.
Se la protektita peto tamen sekvas la tunelon, la protekta alvoko probable okazas post kiam la soketo jam estis enkursigita. Movu ĝin pli frue kaj testu denove.
Tenu la decidon skribitan apud la transporta agordo: kiuj soketoj estas protektitaj, kiu aplikaĵa trafiko estas ekskludita, kaj kion la aplikaĵo faras kiam protekto malsukcesas. Ĝuste tiu linio malhelpas postan refaktorigon vastigi la ekskludon al la tuta aplikaĵo ĉar unu sola testo malsukcesis. Ĝi ankaŭ donas al la sekva persono manieron kontroli la intencon sen retroinĝenierado de la manifesto.