La kontrolo, kiun plej multaj Android-aplikaĵoj uzas por rilati VPN-on, estas interfaca nomo, kaj ĝi neniam estis VPN-kontrolo. Ĝi raportas, ke ekzistas ia interfaco kun ĉeno, kiun la programisto atendis, kio sur unu aparato signifas OpenVPN kaj sur alia signifas ion tute senrilatan. Ping estas la sama speco de pruvo: ĝi pruvas, ke unu celloko respondis, ne ke tunelo portis la paketon. Tio, kion la platformo efektive elmetas, estas aro da retoj kaj la transportoj, kiujn ĉiu el ili deklaras, kaj tio estas alia demando kun alia respondo.

Mito: se tun0 ekzistas, VPN estas aktiva

Android-aj VPN-aplikaĵoj estas VpnService-realigoj, kiuj transdonas al la sistemo dosierpriskribilon tun. La interfaca nomo venas de tiu, kiu kreis ĝin: OpenVPN kutime produktas tun0, PPTP kaj L2TP produktas ppp0, WireGuard nomas sian interfacon laŭ la tunelo, kaj IPsec-tunelo eble tute ne prezentas konvencian nomon. Legi /proc/net/dev aŭ listigi NetworkInterface-objektojn do serĉas konvencion, ne fakton.

Ambaŭ eraraj direktoj estas vivaj. Aparato povas havi tun0 por loka tunelo tute senrilata al la VPN de la uzanto, kaj tute sana WireGuard-tunelo povas esti nevidebla por kontrolo, kiu konas nur la ĉenon tun0. Malveraj pozitivoj kaj malveraj negativoj en la sama funkcio igas ĝin neuzebla kiel diagnozilo, ĉar subtenbileto, kiu diras „neniu VPN trovita“, ne povas esti fidata en iu ajn direkto.

Ankaŭ la aliro mallarĝiĝis. Pli novaj Android-eldonoj limigas, kion ordinara aplikaĵo povas legi el /proc, do nom-bazita kontrolo, kiu funkciis en Android 8, povas redoni malplenan liston sur pli posta aparato sen iu ajn ŝanĝo de kodo. Kiam la kontrolo silente malsukcesas malferme, la aplikaĵo konkludas, ke ne estas VPN sur aparataro, kie la tunelo estas en ordo.

Mito: sukcesa ping signifas, ke la tunelo portas trafikon

Ping al interna gastiganto sukcesas ĉiam, kiam ekzistas vojo al tiu gastiganto. Kun dividita tunelado la gastiganto povas esti atingebla per Wi-Fi dum la tunelo estas aktiva kaj faras tute alian aferon. Kun VPN por unuopa aplikaĵo, la aplikaĵo, kiu faras la ping, povas esti ekskludita el la tunelo, do la ICMP-ekoo eliras ekster ĝi kaj revenas, kio pruvas la malon de tio, kion la kontrolo supozas.

ICMP kaj TCP ankaŭ estas filtritaj aparte. Tunelo, kiu permesas eko-petojn sed forĵetas la TCP-pordon, kiun servo bezonas, trapasos la ping-teston kaj malsukcesos en la aplikaĵo, kaj tio estas fajroŝirma regulo ĉe la malproksima flanko, ne eco de la aparato. La sola honesta legado de sukcesa ping estas, ke ĉi tiu celloko respondis al ĉi tiu protokolo en ĉi tiu momento.

Kion la platformo efektive raportas

De API 21 pluen, ConnectivityManager.getAllNetworks() redonas ĉiun reton, kiun la sistemo konas, kaj getNetworkCapabilities(network) raportas, kion tiu reto deklaras. VPN-reto portas TRANSPORT_VPN. Iteri tra ĉiuj retoj respondas unu demandon: ĉu iu VPN estas nun aktiva sur ĉi tiu aparato?

Dua, pli mallarĝa demando bezonas alian vokon. getActiveNetwork() redonas la reton, kiun la trafiko de la aplikaĵo uzus nun, kaj kontroli la saman kapablon sur ĝi respondas: ĉu mia trafiko irus tra VPN? La du povas malkonsenti, kaj la malkonsento estas informa. VPN, kiu estas aktiva sed ne nuna, indikas per-aplikaĵan vojigon aŭ dividitan tunelan agordon, ne mankantan tunelon.

Network active = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
boolean viaVpn = caps != null
    && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);

Gardu ambaŭ vokojn. Kapabloj povas esti null por reto, kiu malaperis inter listigo kaj demandado, kaj la aktiva reto povas esti null dum transdono. NET_CAPABILITY_NOT_VPN utilas en la alia direkto, por konfirmi, ke reto definitive ne estas tunelo, anstataŭ nur manki al ĝi la VPN-transportan flagon.

NetworkInfo estis la sama mito kun API

ConnectivityManager.TYPE_VPN kun NetworkInfo estas la dua generacio de ĉi tiu kontrolo, kaj ĝi estas eksmoda pro kialo. En modernaj eldonoj la objekto redonita por VPN povas esti null dum la tunelo estas konektita, do kodo, kiu traktas null kiel „neniu VPN“, silente raportas malveran negativon sur la aparatoj, kie la respondo plej gravas.

Ankaŭ la dissendo, kiu kutime akompanas ĝin, ne pli bonas. CONNECTIVITY_CHANGE havas dokumentitan historion de maltrafitaj VPN-transiroj, inkluzive de kunmetaĵoj, kie ĝi ekfunkciis nur kiam VPN konektiĝis aŭ malkonektiĝis, anstataŭ ĉe ĉiu reta ŝanĝo. Aŭskultanto konstruita sur ĝi produktas statan variablon, kiu drivas for de la vido de la platformo ĝis la sekva plena rekonekto.

Reagiru al retrovokoj anstataŭ enketi

Registru NetworkRequest, kiu postulas TRANSPORT_VPN kaj forigas NET_CAPABILITY_NOT_VPN, poste voku registerNetworkCallback kun tiu peto. Tiam onAvailable kaj onLost diras al vi, kiam la deklaro ŝanĝiĝas, kaj tio estas la evento, kiu vere gravas al vi. Malregistru la retrovokon, kiam la komponento haltas, alie la aplikaĵo tenas referencon al morta ekrano kaj la retrovoko daŭre ekfunkcias.

NetworkRequest req = new NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
    .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    .build();
cm.registerNetworkCallback(req, callback);

Tio bezonas ACCESS_NETWORK_STATE, kiu estas normala permeso: neniu root, neniu uzanta konsenta dialogo, neniu VPN-permeso. Enketado per tempigilo estas la alternativo, al kiu homoj revenas, kaj ĝi bruligas baterion dum ĝi ankoraŭ maltrafas transiron pli mallongan ol la intervalo, kio estas ĝuste la transiro, kiun uzanto raportas.

Kion la respondo ankoraŭ ne povas diri al vi

Neniu el ĉi tiuj API raportas, ĉu la tunelo estas sana, en kiu servilo ĝi finiĝas, aŭ ĉu la trafiko de certa aplikaĵo estas ene de ĝi. VPN-reto povas ekzisti sen uzeblaj vojoj, kaj per-aplikaĵa tunelo povas ekskludi la aplikaĵon, kiu starigas la demandon.

Do registru, kion la kontrolo vidis, ne nur la boolean. Registru la retan identigilon, la deklaritajn transportojn kaj ĉu tiu reto estis aktiva. Raporto, kiu diras „neniu VPN trovita“, estas neuzebla, dum unu, kiu diras, ke reto deklaris TRANSPORT_VPN sed getActiveNetwork() redonis Wi-Fi, montras rekte al vojigo aŭ al ekskluda listo, kaj tio estas ripeto, pri kiu iu povas labori.

Rilataj artikoloj