A VpnService védelem meghiúsul, ha már aktív egy másik VPN
Az Android felhasználónként egy VPN-interfészt engedélyez. Futtassa a prepare, establish, protect és tulajdonosi ellenőrzéseket sorrendben, majd válasszon visszavonást vagy alkalmazásonkénti kizárást.
Az alkalmazás meghívja a VpnService.prepare-t, null-t kap, alagutat épít, és a leíró érvényesnek tűnik, mégsem ér el semmi a kiszolgálót. Vagy a prepare Intentet ad vissza, a felhasználó jóváhagyja, és az establish továbbra is meghiúsul. Mindkét eredmény általában ugyanazt jelenti: egy másik alkalmazás már birtokolja a VPN-interfészt ehhez a felhasználóhoz, és a protect hívásai olyan socketeket jelölnek meg, amelyeket az alagút nem tud használni. Vegye sorra az alábbi ellenőrzéseket, és álljon meg az elsőnél, amely meghiúsul, mert egy későbbi lépés nem tud javítani egy korábbin.
Ellenőrizze a VPN-helyet, mielőtt a protecthez nyúlna
Az Android minden felhasználónak pontosan egy aktív VPN-interfészt ad. Ez platformszabály, nem engedély, amelyet az alkalmazás kérhet, ezért két kliens, amelyik egyaránt az alagút akar lenni, nem létezhet egymás mellett.
A másik alkalmazáshoz beállított mindig bekapcsolt VPN a legnehezebb eset, mert a rendszer kapcsolatban tartja azt az alkalmazást, és elutasítja az átvételt. Egy forgalomszűrő, például az AdGuard, egy vállalati kliens vagy egy fogyasztói VPN tarthatja a helyet, miközben a felhasználó elfelejtette, hogy telepítve van. Kérje meg a felhasználót, hogy nyissa meg a Beállításokat, és olvassa el a VPN alatt felsorolt bejegyzést; az ott szereplő név az a tulajdonos, amellyel versenyez. Amíg azt a bejegyzést nem bontják meg, vagy a mindig bekapcsolt beállítást nem törlik, a VpnService nem válhat interfésszé.
Lépés 1: olvassa el, mit ad vissza a prepare
A VpnService.prepare egyetlen kérdésre válaszol: válhat ez az alkalmazás VPN-né? Null-t ad vissza, ha a hozzájárulás már megvan, és Intentet, ha a felhasználónak még jóvá kell hagynia, amelyet startActivityForResult segítségével kell elindítania. Tekintse a null visszaadását a folytatás engedélyének, nem annak bizonyítékának, hogy az establish sikerülni fog.
Intent intent = VpnService.prepare(context);
if (intent != null) {
startActivityForResult(intent, REQUEST_VPN);
}Ha az Intent útvonala visszatér, és a felhasználó elutasította, a prepare a következő próbálkozásnál is Intentet ad vissza. Naplózza az eredménykódot a ciklusos újrapróbálkozás helyett, mert az elutasított hozzájárulás a felhasználó döntése, nem átmeneti hiba.
Lépés 2: erősítse meg, hogy az interfész az ön alkalmazásához tartozik
Az establish után kapott ParcelFileDescriptor a tulajdonjogának bizonyítéka, és érdemes bármilyen socket-munka előtt ellenőrizni. A null vagy már zárt leíró azt jelenti, hogy az interfész soha nem jött létre, még akkor sem, ha nem jelent meg kivétel. Hasonlítsa össze a builder interfésznevét azzal, amelyet a rendszer az aktív VPN-hez bejelent, dumpsys használatával egy teszthelyzetű eszközön. Ha eltérnek, az ön által épített alagút nem az az alagút, amely a forgalmat viszi.
adb shell dumpsys connectivityUgyanez az eltérés magyarázza a csatlakozott ikont halott forgalommal. A rendszer a másik alkalmazás alagútját mutatja, miközben az ön kódja egy olyan interfész leíróját tartja, amely nem az övé.
Lépés 3: hívja meg a protectet a connect előtt
Amint létezik az interfész, az alkalmazás által megnyitott socketek alapértelmezés szerint az alagútba irányulnak. A külső szállítás nem követheti ezt a szabályt, különben a beágyazott csomag visszatérne az interfészbe, ezért VpnService protect megjelöl egy socketet, hogy megkerülje a VPN-t, és a mögöttes hálózatot használja. A hívás egy booleant ad vissza, és ennek figyelmen kívül hagyása az út ahhoz, hogy egy egészségesnek látszó, mégis semmit nem szállító sockethez jusson.
Hívja meg a protectet a connect vagy a bind előtt, soha utána. A védelemnek már a socket csatlakoztatása vagy kötése előtt a helyén kell lennie, mert a csatlakoztatott socket már kiválasztotta az útvonalát, és egy későbbi protect nem mozgatja megbízhatóan. Ha a protect false-t ad vissza, álljon meg, és ellenőrizze újra a tulajdonjogot: akkor hibázik, ha az interfész nem az ön alkalmazásához tartozik, ami pontosan az az állapot, amelyet egy másik VPN maga után hagy. A false visszatérés azt jelzi, hogy térjen vissza a Lépés 1-hez, ne pedig ugyanazt a socketet próbálja újra.
DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
return;
}
socket.connect(serverAddress, serverPort);Lépés 4: kössön egy folyamatot, ha a socket kényelmetlen
Egyes szállítások nem egyetlen socket: egy könyvtár többet is megnyithat, vagy szeretné, ha egy segédfolyamat minden kapcsolata ugyanazt a kimenetet használná. A ConnectivityManager.bindProcessToNetwork a folyamatot egy kiválasztott hálózathoz köti, és a régebbi setProcessDefaultNetwork ugyanezt tette, mielőtt elavulttá vált. Kérje a mögöttes kapcsolatot a NET_CAPABILITY_NOT_VPN jelzővel, hogy a kötés az alagút alatti hálózatot válassza, ne magát az alagutat.
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();Egy folyamat kötése nem második VPN. Kimenetet választ annak a folyamatnak, ami hasznos a szállításhoz, és haszontalan két alagút egyidejű futtatásához.
A felhasználó eszközét javítsa, ne a kód útvonalát
Nincs olyan API, amely lehetővé tenné, hogy két alkalmazás megossza a VPN-helyet, ezért a javítás az eszköz állapotához tartozik. Kínáljon a felhasználónak két konkrét utat: bontsa meg vagy törölje a másik alkalmazás mindig bekapcsolt beállítását, hogy a prepare átvehesse, vagy nyissa meg annak az alkalmazásnak az alkalmazásonkénti beállításait, és zárja ki saját alkalmazását annak alagútjából. A kizárás futva tartja a szűrőt minden más számára, és hagyja, hogy alkalmazása a szokásos kapcsolatot használja, ami gyakran az az eredmény, amelyet a felhasználó valójában szeretne.
Írja le mindkét utat a támogatási dokumentációjában, mert a felhasználók ritkán tudják, melyik alkalmazás birtokolja a VPN-t. Kérje meg őket, hogy küldjék el az aktív VPN nevét a Beállításokból és a prepare, establish és protect eredményeit a naplóiból, és egy percen belül megmondhatja, melyik lépés hibázott. Ezután valódi forgalommal ellenőrizze: névfeloldás, TCP-kapcsolat és egyetlen kérés az alagúton át, nem csak egy csatlakozott ikon. Az érvényes leíró és a zöld jelzés legfeljebb a tulajdonjogot bizonyítja, soha nem azt, hogy a szállítás túlélte az útválasztási szabályokat.
Ha mind a négy ellenőrzés átmegy, és a forgalom mégis elhal, a tulajdonjog már nem az ön problémája. Lépjen tovább az útválasztásra és a kiszolgáló elérhetőségére, és tesztelje ugyanazokat a hitelesítő adatokat egy VPN-alkalmazás nélküli eszközről.