D'Prüfung, déi déi meeschten Android-Appen benotzen, fir eng VPN z'erkennen, ass en Interface-Numm, an et war ni eng VPN-Prüfung. Si mellt, datt en Interface mat enger Zeechenketten existéiert, déi den Entwéckler erwaart huet, wat op engem Apparat OpenVPN bedeit an op engem aneren eppes ganz Onverbonnenes. E Ping ass déi selwecht Zort Beweis: en beweist, datt een Zil geäntwert huet, net datt en Tunnel de Pak gedroen huet. Wat d'Plattform tatsächlech exponéiert, ass eng Rei Netzwierker an d'Transporter, déi jiddereen deklaréiert, an dat ass eng aner Fro mat enger anerer Äntwert.

Mythos: wann tun0 existéiert, ass eng VPN un

Android-VPN-Appen si VpnService-Implementéierungen, déi dem System en tun-Dateideskriptor ginn. Den Interface-Numm kënnt vun deem, deen en erstallt huet: OpenVPN produzéiert normalerweis tun0, PPTP an L2TP produzéieren ppp0, WireGuard nennt säin Interface nom Tunnel, an en IPsec-Tunnel huet vläicht guer keen konventionellen Numm. Dofir sicht d'Liese vun /proc/net/dev oder d'Opziele vun NetworkInterface-Objete no enger Konventioun, net no engem Fakt.

Déi zwou Fehlerrichtunge si lieweg. En Apparat kann tun0 fir en lokalen Tunnel hunn, deen näischt mam VPN vum Benotzer ze dinn huet, an en komplett gesonden WireGuard-Tunnel kann onsichtbar sinn fir eng Prüfung, déi just d'Zeechenkett tun0 kennt. Falsch Positiver a falsch Negativer an der selwechter Funktioun maachen se onbrauchbar als Diagnos, well engem Supportsticket, dee seet „keng VPN fonnt“, a keng Richtung ze vertrauen ass.

Den Zougang ass och méi enk ginn. Méi nei Android-Versiounen beschränken, wat eng gewéinlech App aus /proc liese kann, sou datt eng nummbaséiert Prüfung, déi op Android 8 funktionéiert huet, op engem méi spéiden Apparat eng eidel Lëscht zréckginn kann ouni eng Codeännerung. Wann d'Prüfung stillech an déi oppe Richtung feelt, schléisst d'App, datt et keng VPN gëtt op Hardware, wou den Tunnel an der Rei ass.

Mythos: en erfollegräiche Ping bedeit, datt den Tunnel Verkéier dréit

E Ping op en internen Host geléngt ëmmer, wann eng Route op deen Host existéiert. Mat Split-Tunnelling kann den Host iwwer Wi-Fi erreechbar sinn, wärend den Tunnel un ass an eppes ganz anescht mécht. Mat enger Per-App-VPN kann d'App, déi de Ping mécht, vum Tunnel ausgeschloss sinn, sou datt den ICMP-Echo dobausse geet an zréckkënnt, wat d'Géigendeel vun deem beweist, wat d'Prüfung unhëlt.

ICMP an TCP ginn och getrennt gefiltert. En Tunnel, deen Echo-Ufroe erlaabt, awer de TCP-Port verwerft, deen en Service brauch, wäert den Ping-Test bestoen an an der App versoen, an dat ass eng Firewall-Reeg op der anerer Säit an net eng Eegenschaft vum Apparat. Déi eenzeg éierlech Liesung vun engem erfollegräiche Ping ass, datt dëst Zil dëse Protokoll an dësem Moment geäntwert huet.

Wat d'Plattform tatsächlech mellt

Vun API 21 un gëtt ConnectivityManager.getAllNetworks() all Netzwierk zréck, dat de System kennt, an getNetworkCapabilities(network) mellt, wat dat Netzwierk deklaréiert. En VPN-Netzwierk dréit TRANSPORT_VPN. Duerch all Netzwierker ze goen äntwert op eng Fro: ass just elo eng VPN op dësem Apparat un?

Eng zweet, méi enk Fro brauch en aneren Opruff. getActiveNetwork() gëtt dat Netzwierk zréck, dat den Trafik vun der App just elo benotze géif, an d'Prüfung vun der selwechter Fäegkeet drop äntwert: géif mäin Trafik duerch eng VPN goen? Déi zwou kënnen net iwwereneestëmmen, an d'Differenz ass informativ. Eng VPN, déi un ass, awer net aktuell, weist op Per-App-Routing oder eng Split-Tunnel-Konfiguratioun, net op en fehlenden Tunnel.

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

Séchert béid Opruffer of. Fäegkeeten kënnen null sinn fir en Netzwierk, dat tëscht Oplëschtung a Fro verschwonnen ass, an dat aktivt Netzwierk kann null sinn wärend enger Iwwerleeung. NET_CAPABILITY_NOT_VPN ass an der anerer Richtung nëtzlech, fir ze bestätegen, datt en Netzwierk bestëmmt keen Tunnel ass, amplaz just de VPN-Transport-Fändel ze verpassen.

NetworkInfo war dee selwechte Mythos mat enger API

ConnectivityManager.TYPE_VPN mat NetworkInfo ass déi zweet Generatioun vun dëser Prüfung, an se ass aus engem Grond veraltert. Op moderne Versiounen kann dat Objet, dat fir eng VPN zréckgëtt, null sinn, wärend den Tunnel verbonnen ass, sou datt Code, deen null als „keng VPN“ behandelt, stillech e falscht Negativt op deenen Apparater mellt, wou d'Äntwert am meeschten zielt.

D'Ausstrahlung, déi se normalerweis begleet, ass och net besser. CONNECTIVITY_CHANGE huet eng dokumentéiert Geschicht vu verpasste VPN-Iwwergäng, dorënner Builds, wou se just ausgeléist huet, wann eng VPN sech verbonnen oder getrennt huet, amplaz bei all Netzwierkännerung. E Lauschterer, deen drop opgebaut ass, produzéiert eng Zoustandsvariabel, déi vun der Siicht vun der Plattform fortgeet bis zum nächsten kompletten Neiverbindung.

Reagéiert op Callbacks amplaz ze polleren

Registréiert eng NetworkRequest, déi TRANSPORT_VPN verlaangt an NET_CAPABILITY_NOT_VPN ewechhëlt, a rufft dann registerNetworkCallback mat där Ufro op. Dann soen onAvailable an onLost Iech, wéini d'Deklaratioun sech ännert, an dat ass d'Evenement, dat Iech wierklech interesséiert. Huet d'Callback-Registréierung op, wann de Komponent stoppt, soss hält d'App eng Referenz op en doudegen Écran an de Callback geet weider lass.

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

Dëst brauch ACCESS_NETWORK_STATE, wat eng normal Erlaabnis ass: keen Root, keen Dialog fir d'Zoustëmmung vum Benotzer, keng VPN-Erlaabnis. Polling mat engem Timer ass d'Alternativ, op déi d'Leit zréckgräifen, an et verbrennt Batterie, wärend et nach ëmmer en Iwwergang verpasst, dee méi kuerz ass wéi den Intervall, an dat ass genee den Iwwergang, deen e Benotzer mellt.

Wat d'Äntwert nach ëmmer net soe kann

Keen vun dësen APIen mellt, ob den Tunnel gesond ass, op wéi engem Server en endet oder ob den Trafik vun enger bestëmmter App dobannen ass. En VPN-Netzwierk kann ouni brauchbar Route existéieren, an en Per-App-Tunnel kann d'App ausschléissen, déi d'Fro stellt.

Dofir registréiert, wat d'Prüfung gesinn huet, net just de Boolean. Logt den Netzwierk-Identifiant, déi deklaréiert Transporter an ob dat Netzwierk aktiv war. E Rapport, dee seet „keng VPN fonnt“, ass onbrauchbar, wärend een, dee seet, e Netzwierk hätt TRANSPORT_VPN deklaréiert, awer getActiveNetwork() hätt Wi-Fi zréckginn, direkt op Routing oder op eng Ausschlosslëscht weist, an dat ass eng Korrektur, un där een schaffe kann.

Ähnlech Artikelen