VpnService-ի պաշտպանությունը ձախողվում է, երբ մեկ այլ VPN արդեն ակտիվ է
Android-ը թույլատրում է մեկ VPN ինտերֆեյս յուրաքանչյուր օգտագործողի համար։ Կատարեք prepare, establish, protect և սեփականության ստուգումները հերթականությամբ, ապա ընտրեք չեղարկում կամ հավելվածով բացառում։
Ձեր հավելվածը կանչում է VpnService.prepare, ստանում null, կառուցում թունել, և նկարագրիչը վավեր է թվում, բայց ոչինչ չի հասնում սերվերին։ Կամ prepare-ը վերադարձնում է Intent, օգտագործողը հաստատում է այն, և establish-ը միևնույն է ձախողվում է։ Երկու արդյունքները սովորաբար նշանակում են նույնը՝ մեկ այլ հավելված արդեն տիրապետում է այս օգտագործողի VPN ինտերֆեյսին, և ձեր protect կանչերը նշում են սոքեթներ, որոնք ձեր թունելը չի կարող օգտագործել։ Անցեք ստորև նշված ստուգումները հերթականությամբ և կանգ առեք առաջին ձախողվածի վրա, քանի որ հետագա քայլը չի կարող վերականգնել նախորդը։
Ստուգեք VPN տեղը նախքան protect-ին դիպչելը
Android-ը յուրաքանչյուր օգտագործողի տալիս է ճիշտ մեկ ակտիվ VPN ինտերֆեյս։ Սա հարթակի կանոն է, ոչ թե թույլտվություն, որը ձեր հավելվածը կարող է խնդրել, ուստի երկու հաճախորդներ, որոնք երկուսն էլ ցանկանում են լինել թունելը, չեն կարող գոյատևել միասին։
Մեկ այլ հավելվածի համար սահմանված մշտապես միացված VPN-ը ամենադժվար դեպքն է, որովհետև համակարգը պահում է այդ հավելվածը միացված և մերժում է վերցնումը։ AdGuard-ի նման երթևեկության զտիչը, կորպորատիվ հաճախորդը կամ սպառողական VPN-ը կարող են զբաղեցնել տեղը, մինչ օգտագործողը մոռացել է, որ այն տեղադրված է։ Խնդրեք օգտագործողին բացել Կարգավորումները և կարդալ VPN-ի տակ նշված մուտքը, այնտեղի անունը այն սեփականատերն է, որի հետ դուք մրցում եք։ Քանի դեռ այդ մուտքը անջատված չէ կամ մշտապես միացված կարգավորումը ջնջված չէ, ձեր VpnService-ը չի կարող դառնալ ինտերֆեյս։
Քայլ 1: կարդացեք, թե ինչ է վերադարձնում prepare-ը
VpnService.prepare-ը պատասխանում է մեկ հարցի՝ կարող է այս հավելվածը դառնալ VPN։ Այն վերադարձնում է null, երբ համաձայնությունն արդեն կա, և Intent, երբ օգտագործողը դեռ պետք է հաստատի այն, ինչը դուք պետք է գործարկեք startActivityForResult-ով։ null-ի վերադարձը ընդունեք որպես շարունակելու թույլտվություն, ոչ որպես ապացույց, որ establish-ը կհաջողվի։
Intent intent = VpnService.prepare(context);
if (intent != null) {
startActivityForResult(intent, REQUEST_VPN);
}Եթե Intent-ի ուղին վերադառնում է և օգտագործողը մերժել է, prepare-ը հաջորդ փորձին նորից Intent կվերադարձնի։ Գրանցեք արդյունքի կոդը ցիկլում կրկին փորձելու փոխարեն, որովհետև մերժված համաձայնությունը օգտագործողի որոշում է, ոչ թե անցողիկ սխալ։
Քայլ 2: հաստատեք, որ ինտերֆեյսը պատկանում է ձեր հավելվածին
establish-ից հետո ստացված ParcelFileDescriptor-ը ձեր սեփականության ապացույցն է, և արժե ստուգել այն ցանկացած սոքեթ աշխատանքից առաջ։ null կամ արդեն փակ նկարագրիչը նշանակում է, որ ինտերֆեյսը երբեք չի ստեղծվել, նույնիսկ եթե բացառություն չի հայտնվել։ Համեմատեք builder-ի ինտերֆեյսի անունը համակարգի՝ ակտիվ VPN-ի համար հաղորդած անվան հետ՝ փորձնական սարքում օգտագործելով dumpsys։ Եթե դրանք տարբերվում են, ձեր կառուցած թունելը այն թունելը չէ, որը կրում է երթևեկությունը։
adb shell dumpsys connectivityՆույն անհամապատասխանությունը բացատրում է միացված պատկերակը մեռած երթևեկությամբ։ Համակարգը ցույց է տալիս մյուս հավելվածի թունելը, մինչդեռ ձեր կոդը պահում է ինտերֆեյսի նկարագրիչ, որը իրենը չէ։
Քայլ 3: կանչեք protect-ը connect-ից առաջ
Երբ ինտերֆեյսը գոյություն ունի, ձեր հավելվածի բացած սոքեթները լռելյայն ուղղորդվում են թունել։ Արտաքին տրանսպորտը չի կարող հետևել այդ կանոնին, հակառակ դեպքում փաթեթավորված փաթեթը կվերադառնար ինտերֆեյս, ուստի VpnService protect-ը նշում է սոքեթը՝ շրջանցելու VPN-ը և օգտագործելու հիմքում ընկած ցանցը։ Կանչը վերադարձնում է boolean, և դա անտեսելը հենց այն ուղին է, որով հայտնվում եք առողջ տեսք ունեցող, բայց ոչինչ չկրող սոքեթով։
Կանչեք protect-ը connect-ից կամ bind-ից առաջ, երբեք հետո։ Պաշտպանությունը պետք է տեղում լինի նախքան սոքեթի միացումը կամ կապումը, որովհետև միացված սոքեթն արդեն ընտրել է իր ուղին, և ավելի ուշ protect-ը հուսալիորեն չի տեղափոխում այն։ Եթե protect-ը վերադարձնում է false, կանգ առեք և նորից ստուգեք սեփականությունը, այն ձախողվում է, երբ ինտերֆեյսը ձեր հավելվածինը չէ, ինչը հենց այն վիճակն է, որ թողնում է մեկ այլ VPN։ false-ի վերադարձը ազդանշան է վերադառնալ Քայլ 1, ոչ թե նույն սոքեթը նորից փորձել։
DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
return;
}
socket.connect(serverAddress, serverPort);Քայլ 4: կապեք պրոցեսը, երբ սոքեթը անհարմար է
Որոշ տրանսպորտներ մեկ սոքեթ չեն, գրադարանը կարող է բացել մի քանիսը, կամ դուք կարող եք ցանկանալ, որ օժանդակ պրոցեսի յուրաքանչյուր կապ օգտագործի նույն ելքը։ ConnectivityManager.bindProcessToNetwork-ը պրոցեսը կապում է ընտրված ցանցին, և հին setProcessDefaultNetwork-ը նույնն էր անում նախքան հնացած դառնալը։ Պահանջեք հիմքում ընկած կապը NET_CAPABILITY_NOT_VPN-ով, որպեսզի կապումը ընտրի ձեր թունելի տակ գտնվող ցանցը, ոչ թե ինքը թունելը։
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();Պրոցես կապելը երկրորդ VPN չէ։ Այն ընտրում է ելք այդ պրոցեսի համար, ինչը օգտակար է ձեր տրանսպորտի համար և անօգուտ՝ միաժամանակ երկու թունել վարելու համար։
Ուղղեք օգտագործողի սարքը, ոչ թե կոդի ուղին
Չկա API, որը թույլ է տալիս երկու հավելվածի կիսել VPN տեղը, ուստի ուղղումը սարքի վիճակինն է։ Առաջարկեք օգտագործողին երկու կոնկրետ ուղի, անջատեք կամ ջնջեք մյուս հավելվածի մշտապես միացվածը, որպեսզի ձեր prepare-ը կարողանա վերցնել, կամ բացեք այդ հավելվածի հավելվածով կարգավորումները և բացառեք ձեր հավելվածը նրա թունելից։ Բացառումը զտիչը պահում է աշխատող մնացած ամեն ինչի համար և թույլ է տալիս ձեր հավելվածին օգտագործել սովորական կապը, ինչը հաճախ հենց այն արդյունքն է, որ օգտագործողը իրականում ուզում է։
Գրեք երկու ուղիներն էլ ձեր աջակցության փաստաթղթերում, որովհետև օգտագործողները հազվադեպ գիտեն, թե որ հավելվածն է տիրապետում VPN-ին։ Խնդրեք նրանց ուղարկել ակտիվ VPN-ի անունը Կարգավորումներից և prepare, establish ու protect-ի արդյունքները ձեր մատյաններից, և մեկ րոպեում կարող եք ասել, թե որ քայլը ձախողվեց։ Այնուհետև ստուգեք իրական երթևեկությամբ, անվան որոնում, TCP կապ և մեկ հարցում թունելով, ոչ միայն միացված պատկերակ։ Վավեր նկարագրիչը և կանաչ ցուցիչը լավագույն դեպքում ապացուցում են սեփականությունը, երբեք այն, որ տրանսպորտը վերապրել է երթուղավորման կանոնները։
Եթե բոլոր չորս ստուգումները անցնում են, և երթևեկը դեռ մեռնում է, սեփականությունն այլևս ձեր խնդիրը չէ։ Անցեք երթուղավորմանը և սերվերի հասանելիությանը, և ստուգեք նույն հավատարմագրերը VPN հավելված չունեցող սարքից։