Að greina VPN á Android: hvers vegna tun0 og ping villa um fyrir
Heiti tengis er venja; ping sannar að einn vél var aðgengileg. Spurðu NetworkCapabilities hvað net lýsir yfir, og bregðast síðan við köllum.
Athugunin sem flestar Android-forrit nota til að greina VPN er heiti tengis, og hún hefur aldrei verið VPN-athugun. Hún tilkynnir að eitthvert tengi sé til með strengnum sem forritarinn bjóst við, sem á einu tæki þýðir OpenVPN og á öðru þýðir eitthvað algjörlega ótengt. Ping er sama tegund sönnunar: það sannar að einn áfangastaður svaraði, ekki að göng hafi flutt pakkann. Það sem kerfið býður í raun er mengi neta og flutningarnir sem hvert þeirra lýsir yfir, og það er önnur spurning með annað svar.
Goðsögn: ef tun0 er til, er VPN í gangi
Android VPN-forrit eru VpnService-útfærslur sem afhenda kerfinu tun skráarlýsingu. Heiti tengisins kemur frá þeim sem bjó það til: OpenVPN framleiðir venjulega tun0, PPTP og L2TP framleiða ppp0, WireGuard nefnir tengi sitt eftir göngunum, og IPsec-göng kunna ekki að sýna neitt hefðbundið heiti yfirleitt. Því leitar lestur /proc/net/dev eða talning NetworkInterface-hluta að venju, ekki staðreynd.
Báðar villustefnurnar eru lifandi. Tæki getur haft tun0 fyrir staðbundið göng sem hefur ekkert með VPN notandans að gera, og fullkomlega heilbrigt WireGuard-göng getur verið ósýnilegt athugun sem þekkir aðeins strenginn tun0. Falskt jákvætt og falskt neikvætt í sömu aðgerð gera hana ónothæfa sem greiningu, því ekki er hægt að treysta stuðningsmiða sem segir „ekkert VPN fannst“ í neina átt.
Aðgangur hefur líka þrengst. Nýrri útgáfur Android takmarka hvað venjulegt forrit má lesa úr /proc, svo athugun byggð á heiti sem virkaði á Android 8 getur skilað tómum lista á nýrra tæki án nokkurrar kóðabreytingar. Þegar athugunin mistekst hljóðlega í opna áttina dregur forritið þá ályktun að ekkert VPN sé á vélbúnaði þar sem göngin eru í lagi.
Goðsögn: árangursríkt ping þýðir að göngin flytja umferð
Ping á innri vél heppnast hvenær sem leið að þeirri vél er til. Með skiptum göngum getur vélin verið aðgengileg um Wi-Fi meðan göngin eru í gangi og gera eitthvað allt annað. Með VPN fyrir hvert forrit getur forritið sem pingar verið útilokað frá göngunum, svo ICMP-bergmálið fer út fyrir þau og kemur til baka, sem sannar hið gagnstæða við það sem athugunin gerir ráð fyrir.
ICMP og TCP eru líka síað hvort fyrir sig. Göng sem leyfa bergmálsbeiðnir en sleppa TCP-gáttinni sem þjónusta þarf munu standast ping-prófið og mistakast í forritinu, og það er eldveggjarregla hinum megin en ekki eiginleiki tækisins. Eina heiðarlega lestur á árangursríku pingi er að þessi áfangastaður svaraði þessari siðareglu á þessari stundu.
Hvað kerfið tilkynnir í raun
Frá API 21 skilar ConnectivityManager.getAllNetworks() hverju neti sem kerfið þekkir, og getNetworkCapabilities(network) tilkynnir hvað það net lýsir yfir. VPN-net ber TRANSPORT_VPN. Að fara í gegnum öll net svarar einni spurningu: er eitthvert VPN í gangi á þessu tæki núna?
Önnur, þrengri spurning krefst annars kalls. getActiveNetwork() skilar því neti sem umferð forritsins myndi nota núna, og að athuga sama getu á því svarar: myndi umferðin mín fara í gegnum VPN? Þau tvö geta verið ósammála, og ósammælið er upplýsandi. VPN sem er í gangi en ekki núverandi bendir á leiðsögn fyrir hvert forrit eða stillingu skiptra ganga, ekki á göng sem vantar.
Network active = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
boolean viaVpn = caps != null
&& caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
Verja bæði köllin. Getur getur verið null fyrir net sem hvarf milli talningar og fyrirspurnar, og virka netið getur verið null við yfirfærslu. NET_CAPABILITY_NOT_VPN er gagnlegt í hina áttina, til að staðfesta að net sé örugglega ekki göng frekar en að það vanti bara VPN-flutningsfánann.
NetworkInfo var sama goðsögn með API
ConnectivityManager.TYPE_VPN með NetworkInfo er önnur kynslóð þessarar athugunar, og hún er úrelt af ástæðu. Í nútímaútgáfum getur hluturinn sem skilað er fyrir VPN verið null meðan göngin eru tengd, svo kóði sem meðhöndlar null sem „ekkert VPN“ tilkynnir hljóðlega falskt neikvætt á þeim tækjum þar sem svarið skiptir mestu.
Útsendingin sem fylgir henni venjulega er ekki betri. CONNECTIVITY_CHANGE hefur skjalfesta sögu um að sleppa VPN-umskiptum, þar á meðal útgáfur þar sem hún hleypti af stað aðeins þegar VPN tengdist eða aftengdist frekar en við hverja netbreytingu. Hlustandi byggður á henni framleiðir stöðubreytu sem rekur frá sýn kerfisins þar til næsta fulla endurtenging.
Bregðast við köllum í stað þess að spyrja reglulega
Skráðu NetworkRequest sem krefst TRANSPORT_VPN og fjarlægir NET_CAPABILITY_NOT_VPN, og kallaðu síðan registerNetworkCallback með þeirri beiðni. Þá segja onAvailable og onLost þér hvenær yfirlýsingin breytist, og það er atburðurinn sem þú hefur raunverulegan áhuga á. Afskráðu kallið þegar hlutinn stöðvast, annars heldur forritið tilvísun í dauðan skjá og kallið heldur áfram að hlaupa.
NetworkRequest req = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();
cm.registerNetworkCallback(req, callback);
Þetta krefst ACCESS_NETWORK_STATE, sem er venjulegt leyfi: ekkert root, enginn samþykkisgluggi notandans, ekkert VPN-leyfi. Regluleg fyrirspurn með tímamæli er sá valkostur sem fólk grípur til, og hún brennir rafhlöðu á meðan hún sleppir samt umskiptum sem eru styttri en bilið, og það er einmitt umskiptin sem notandi tilkynnir.
Hvað svarið getur enn ekki sagt þér
Ekkert þessara API tilkynnir hvort göngin eru heilbrigð, á hvaða þjóni þau enda, eða hvort umferð tiltekins forrits er inni í þeim. VPN-net getur verið til án nothæfra leiða, og göng fyrir hvert forrit geta útilokað forritið sem spyr spurningarinnar.
Skráðu því hvað athugunin sá, ekki bara boolean-gildið. Skráðu auðkenni netsins, yfirlýsta flutninga og hvort það net var virkt. Skýrsla sem segir „ekkert VPN fannst“ er ónothæf, en sú sem segir að net hafi lýst yfir TRANSPORT_VPN en getActiveNetwork() hafi skilað Wi-Fi bendir beint á leiðsögn eða útilokunarlista, og það er lagfæring sem einhver getur unnið með.