Ukaguzi ambao programu nyingi za Android hutumia kugundua VPN ni jina la kiolesura, na haukuwa kamwe ukaguzi wa VPN. Unaripoti kwamba kuna kiolesura chenye mfuatano ambao msanidi alitarajia, jambo ambalo kwenye kifaa kimoja humaanisha OpenVPN na kwenye kingine humaanisha kitu kisichohusiana kabisa. ping ni ushahidi wa aina hiyo hiyo: huthibitisha kwamba lengwa moja lilijibu, si kwamba handaki ilibeba pakiti. Kinachofichua jukwaa kwa kweli ni seti ya mitandao na usafirishaji ambao kila mmoja unatangaza, na hilo ni swali lingine lenye jibu lingine.

Hadithi: ikiwa tun0 ipo, VPN inafanya kazi

Programu za VPN za Android ni utekelezaji wa VpnService ambao hukabidhi mfumo kielekezi cha faili cha tun. Jina la kiolesura hutoka kwa yeyote aliyekiunda: OpenVPN kwa kawaida huzalisha tun0, PPTP na L2TP huzalisha ppp0, WireGuard hukiita kiolesura chake kwa jina la handaki, na handaki ya IPsec inaweza isionyeshe jina la kawaida kabisa. Kwa hiyo kusoma /proc/net/dev au kuhesabu vitu vya NetworkInterface hutafuta mkataba, si ukweli.

Mielekeo yote miwili ya makosa iko hai. Kifaa kinaweza kuwa na tun0 kwa handaki ya ndani isiyohusiana na VPN ya mtumiaji, na handaki ya WireGuard yenye afya kamili inaweza isionekane kwa ukaguzi unaojua tu mfuatano tun0. Matokeo ya uongo chanya na uongo hasi katika kitendakazi kimoja huifanya isiwe na matumizi kama uchunguzi, kwa sababu tikiti ya msaada inayosema «hakuna VPN iliyogunduliwa» haiwezi kuaminiwa upande wowote.

Ufikiaji pia umepungua. Matoleo mapya ya Android hupunguza kile programu ya kawaida inaweza kusoma kutoka /proc, kwa hiyo ukaguzi unaotegemea jina uliofanya kazi kwenye Android 8 unaweza kurudisha orodha tupu kwenye kifaa cha baadaye bila mabadiliko yoyote ya msimbo. Ukaguzi unaposhindwa kimya kuelekea upande wazi, programu huhitimisha kuwa hakuna VPN kwenye maunzi ambapo handaki iko sawa.

Hadithi: ping iliyofanikiwa inamaanisha handaki inabeba trafiki

ping kwa mwenyeji wa ndani hufanikiwa kila mara njia ya kufikia mwenyeji huyo ipo. Kwa handaki iliyogawanywa, mwenyeji anaweza kufikiwa kwa Wi-Fi wakati handaki inafanya kazi na inafanya kitu kingine kabisa. Kwa VPN ya kila programu, programu inayofanya ping inaweza kutengwa na handaki, kwa hiyo mwangwi wa ICMP hutoka nje yake na kurudi, jambo ambalo huthibitisha kinyume cha kile ukaguzi unachodhania.

ICMP na TCP pia huchujwa kwa tofauti. Handaki inayoruhusu maombi ya mwangwi lakini hutupa bandari ya TCP ambayo huduma inahitaji itapita mtihani wa ping na kushindwa kwenye programu, na hilo ni kanuni ya firewall upande wa pili, si sifa ya kifaa. Usomaji pekee wa uaminifu wa ping iliyofanikiwa ni kwamba lengwa hili lilijibu itifaki hii wakati huu.

Jukwaa huaripoti nini kwa kweli

Kuanzia API 21, ConnectivityManager.getAllNetworks() hurudisha kila mtandao ambao mfumo unaujua, na getNetworkCapabilities(network) huaripoti kile mtandao huo unatangaza. Mtandao wa VPN hubeba TRANSPORT_VPN. Kupitia mitandao yote hujibu swali moja: kuna VPN yoyote inayofanya kazi kwenye kifaa hiki sasa?

Swali la pili, jembamba zaidi, linahitaji mwito mwingine. getActiveNetwork() hurudisha mtandao ambao trafiki ya programu ingetumia sasa, na kukagua uwezo huo huo juu yake hujibu: trafiki yangu itapita kwenye VPN? Vyote viwili vinaweza kutokubaliana, na kutokubaliana huko ni chenye taarifa. VPN inayofanya kazi lakini si ya sasa inaelekeza kwenye uelekezaji wa kila programu au usanidi wa handaki iliyogawanywa, si handaki inayokosekana.

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

Linda mwito wote wawili. Uwezo unaweza kuwa null kwa mtandao uliotoweka kati ya kuorodhesha na kuuliza, na mtandao unaofanya kazi unaweza kuwa null wakati wa kuhamisha. NET_CAPABILITY_NOT_VPN ni muhimu kwa upande mwingine, kuthibitisha kwamba mtandao hakika si handaki badala ya kukosa tu bendera ya usafirishaji wa VPN.

NetworkInfo ulikuwa hadithi hiyo hiyo na API

ConnectivityManager.TYPE_VPN pamoja na NetworkInfo ni kizazi cha pili cha ukaguzi huu, na kimepitwa na wakati kwa sababu. Kwenye matoleo ya kisasa kitu kinachorudishwa kwa VPN kinaweza kuwa null wakati handaki imeunganishwa, kwa hiyo msimbo unaochukulia null kama «hakuna VPN» huaripoti kimya hasi ya uongo kwenye vifaa ambapo jibu ni muhimu zaidi.

Hata matangazo yanayoambatana nayo kwa kawaida si bora. CONNECTIVITY_CHANGE ina historia iliyoandikwa ya kukosa mabadiliko ya VPN, ikiwa ni pamoja na matoleo ambapo ilizinduka tu wakati VPN ilipounganishwa au kutenganishwa badala ya kila mabadiliko ya mtandao. Msikilizaji uliojengwa juu yake huzalisha kigezo cha hali kinachojitenga na mtazamo wa jukwaa hadi muunganisho kamili unaofuata.

Itikia callbacks badala ya kuchunguza

Sajili NetworkRequest inayohitaji TRANSPORT_VPN na kuondoa NET_CAPABILITY_NOT_VPN, kisha ita registerNetworkCallback na ombi hilo. Wakati huo onAvailable na onLost hukuambia tamko linabadilika lini, na hilo ni tukio ambalo unajali kweli. Ondoa usajili wa callback wakati sehemu inasimama, vinginevyo programu inashikilia rejeleo la skrini iliyokufa na callback inaendelea kuzinduka.

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

Hii inahitaji ACCESS_NETWORK_STATE, ambayo ni ruhusa ya kawaida: hakuna root, hakuna mazungumzo ya idhini ya mtumiaji, hakuna ruhusa ya VPN. Kuchunguza kwa kipima muda ni mbadala ambao watu huukimbilia, na huchoma betri wakati bado inakosa mabadiliko mafupi kuliko muda, na hayo ni mabadiliko ambayo mtumiaji huripoti.

Kile jibu bado haliwezi kukuambia

Hakuna API hizi inayoripoti kama handaki ina afya, inaishia kwenye seva gani, au kama trafiki ya programu fulani iko ndani yake. Mtandao wa VPN unaweza kuwepo bila njia zinazoweza kutumika, na handaki ya kila programu inaweza kumtenga programu inayouliza swali.

Kwa hiyo rekodi kile ukaguzi uliona, si boolean tu. Rekodi kitambulisho cha mtandao, usafirishaji uliotangazwa na kama mtandao huo ulikuwa hai. Ripoti inayosema «hakuna VPN iliyogunduliwa» haina matumizi, ilhali ile inayosema mtandao ulitangaza TRANSPORT_VPN lakini getActiveNetwork() ilirudisha Wi-Fi inaelekeza moja kwa moja kwenye uelekezaji au orodha ya kutenga, na hilo ni marekebisho ambayo mtu anaweza kufanyia kazi.

Makala zinazohusiana