VpnService-beskerming mislearret as in oare VPN al aktyf is
Android lit ien VPN-ynterface per brûker ta. Rin de kontrôles prepare, establish, protect en eigendom yn folchoarder ôf en kies dan yntrek of útsluting per app.
Jo app ropt VpnService.prepare oan, krijt null werom, bout in tunnel, en de deskriptor liket jildich, mar der komt neat by de tsjinner. Of prepare jout in Intent werom, de brûker stimt dermei yn, en establish mislearret dochs. Beide útkomsten betsjutte meastentiids itselde: in oare app hat al de VPN-ynterface foar dizze brûker, en jo protect-oproppen markearje sockets dy’t jo tunnel net brûke kin. Rin de kontrôles hjirûnder yn folchoarder ôf en stop by de earste dy’t mislearret, want in lettere stap kin in eardere net reparearje.
Kontrolearje it VPN-plak foardat jo protect oanreitsje
Android jout elke brûker krekt ien aktyf VPN-ynterface. Dat is in platfoarmregel, net in tastimming dy’t jo app oanfreegje kin, dus twa klanten dy’t beide de tunnel wêze wolle, kinne net njonkeninoar bestean.
In altyd-oan-VPN dy’t foar in oare app ynsteld is, is it dreechste gefal, want it systeem hâldt dy app ferbûn en wegeret in oername. In ferkearsfilter lykas AdGuard, in bedriuwsclient of in konsuminte-VPN kin it plak hâlde wylst de brûker fergetten is dat it ynstallearre is. Freegje de brûker Ynstellings te iepenjen en it item ûnder VPN te lêzen; de namme dêr is de eigner dêr’t jo mei konkurrearje. Oant dat item ferbrutsen wurdt of de altyd-oan-ynstelling wiske wurdt, kin jo VpnService net de ynterface wurde.
Stap 1: lês wat prepare weromjout
VpnService.prepare beantwurdet ien fraach: mei dizze app de VPN wurde? It jout null werom as der al tastimming is, en in Intent as de brûker dy noch goedkrije moat, dy’t jo mei startActivityForResult starte moatte. Behannelje in null-weromjefte as tastimming om troch te gean, net as bewiis dat establish slagje sil.
Intent intent = VpnService.prepare(context);
if (intent != null) {
startActivityForResult(intent, REQUEST_VPN);
}As it Intent-paad weromkomt en de brûker hat wegere, sil prepare by de folgjende poging wer in Intent jaan. Logje de resultaatkoade ynstee fan yn in lus opnij te besykjen, want in wegere tastimming is in beslút fan de brûker, gjin tydlike flater.
Stap 2: befêstigje dat de ynterface by jo app heart
Nei establish is de ParcelFileDescriptor dy’t jo krije jo bewiis fan eigendom, en it is de muoite wurdich om dy foar alle socket-wurk te kontrolearjen. In deskriptor dy’t null is of al ticht is, betsjut dat de ynterface nea makke is, sels as der gjin útsûndering opkaam. Ferlykje de ynterfacenamme fan de bouwer mei dy’t it systeem foar de aktive VPN rapportearret, mei dumpsys op in testapparaat. As se ferskille, is de tunnel dy’t jo boud hawwe net de tunnel dy’t ferkear draacht.
adb shell dumpsys connectivityDeselde mismatch ferklearret in ferbûn ikoan mei dea ferkear. It systeem lit de tunnel fan de oare app sjen, wylst jo koade in deskriptor hâldt foar in ynterface dy’t er net hat.
Stap 3: rop protect oan foar connect
Sadree’t de ynterface bestiet, wurde sockets dy’t jo app iepent standert yn ’e tunnel rûte. It bûtenste transport kin dy regel net folgje of it ferpakke pakket soe werom yn ’e ynterface rinne, dêrom VpnService protect markearret in socket om de VPN te omgean en it ûnderlizzende netwurk te brûken. De oprop jout in boolean werom, en it negearjen dêrfan is hoe’t jo einigje mei in socket dy’t sûn liket en neat draacht.
Rop protect oan foar connect of bind, nea dêrnei. Beskerming moat yn plak wêze foardat de socket ferbûn of bûn wurdt, want in ferbûne socket hat syn rûte al keazen en in lettere protect ferpleatst him net betrouber. As protect false weromjout, stopje en kontrolearje eigendom opnij: it mislearret as de ynterface net by jo app heart, en dat is krekt de steat dy’t in oare VPN efterlit. In false-weromjefte is in sinjaal om werom te gean nei stap 1, net om deselde socket opnij te besykjen.
DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
return;
}
socket.connect(serverAddress, serverPort);Stap 4: byn in proses as in socket ûnhandich is
Guon transporten binne gjin ien socket: in bibleteek kin der ferskate iepenje, of jo wolle miskien dat elke ferbining yn in helpproses deselde útgong brûkt. ConnectivityManager.bindProcessToNetwork bynt it proses oan in keazen netwurk, en de âldere setProcessDefaultNetwork die itselde foardat it ferâldere wie. Freegje de ûnderlizzende ferbining oan mei NET_CAPABILITY_NOT_VPN, sadat de binding it netwurk ûnder jo tunnel kiest yn stee fan de tunnel sels.
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();In proses byn is gjin twadde VPN. It kiest in útgong foar dat proses, wat nuttich is foar jo transport en nutteloas foar it draaien fan twa tunnels tagelyk.
Reparearje it apparaat fan de brûker, net it koadepaad
Der is gjin API dy’t twa apps it VPN-plak diele lit, dus de oplossing heart by de steat fan it apparaat. Bied de brûker twa konkrete paden: ferbrek of wiskje altyd-oan foar de oare app sadat jo prepare oernimme kin, of iepenje de per-app-ynstellingen fan dy app en slút jo app út fan syn tunnel. De útsluting hâldt it filter oan it wurkjen foar al it oare en lit jo app de gewoane ferbining brûke, wat faak it resultaat is dat de brûker eins wol.
Skriuw beide paden yn jo stypdokumintaasje, want brûkers witte selden hokker app de VPN hat. Freegje se om de namme fan de aktive VPN út Ynstellings en de resultaten fan prepare, establish en protect út jo logboeken te stjoeren, en jo kinne binnen in minút sizze hokker stap mislearre. Ferifiearje dan mei echt ferkear: in namme-opfreage, in TCP-ferbining en ien fersyk troch de tunnel, net allinnich in ferbûn ikoan. In jildige deskriptor en in griene oanwizing bewize op syn bêst eigendom, nea dat it transport de rûte-regels oerlibbe hat.
As alle fjouwer kontrôles slagje en ferkear stjert noch, is eigendom net mear jo probleem. Gean fierder nei rûte en berikberens fan de tsjinner, en test deselde oanmeldgegevens fan in apparaat sûnder VPN-app.