Sizning dasturingiz VpnService.prepare ni chaqiradi, null oladi, tunnel quradi va deskriptor haqiqiy ko‘rinadi, lekin serverga hech narsa yetib bormaydi. Yoki prepare Intent qaytaradi, foydalanuvchi uni tasdiqlaydi, ammo establish baribir ishlamaydi. Ikkala natija odatda bir narsani bildiradi: boshqa dastur bu foydalanuvchining VPN interfeysiga allaqachon egalik qiladi va sizning protect chaqiruvlaringiz tunnellingiz foydalana olmaydigan soketlarni belgilaydi. Quyidagi tekshiruvlarni tartib bilan bajaring va birinchi ishlamaganida to‘xtang, chunki keyingi qadam avvalgisini tuzata olmaydi.

protect ga tegishdan oldin VPN o‘rnini tekshiring

Android har bir foydalanuvchiga aynan bitta faol VPN interfeysi beradi. Bu platforma qoidasi, dasturingiz so‘rashi mumkin bo‘lgan ruxsat emas, shuning uchun ikkisi ham tunnel bo‘lishni xohlaydigan ikki mijoz birga yashay olmaydi.

Boshqa dastur uchun sozlangan doim yoniq VPN eng qiyin holat, chunki tizim o‘sha dasturni ulangan holda saqlaydi va egallashdan bosh tortadi. AdGuard kabi trafik filtri, korporativ mijoz yoki iste’molchi VPN foydalanuvchi u o‘rnatilganini unutgan paytda o‘rinni egallashi mumkin. Foydalanuvchidan Sozlamalarni ochib VPN ostida ko‘rsatilgan yozuvni o‘qishni so‘rang; u yerdagi nom siz raqobatlashayotgan egadir. O‘sha yozuv uzilmaguncha yoki doim yoniq sozlamasi o‘chirilmaguncha, sizning VpnService interfeys bo‘la olmaydi.

Qadam 1: prepare nima qaytarishini o‘qing

VpnService.prepare bitta savolga javob beradi: bu dastur VPN bo‘la oladimi? Rozilik allaqachon bo‘lsa null, foydalanuvchi hali tasdiqlashi kerak bo‘lsa Intent qaytaradi, uni startActivityForResult bilan ishga tushirish kerak. null qaytishini davom etish ruxsati deb biling, establish muvaffaqiyatli bo‘lishining isboti emas.

Intent intent = VpnService.prepare(context);
if (intent != null) {
    startActivityForResult(intent, REQUEST_VPN);
}

Agar Intent yo‘li qaytsa va foydalanuvchi rad etgan bo‘lsa, prepare keyingi urinishda yana Intent qaytaraveradi. Siklda qayta urinish o‘rniga natija kodini yozib qo‘ying, chunki rad etilgan rozilik foydalanuvchi qarori, vaqtinchalik xato emas.

Qadam 2: interfeys dasturingizga tegishli ekanini tasdiqlang

establish dan keyin olingan ParcelFileDescriptor egaligingizning isboti, va har qanday soket ishidan oldin uni tekshirishga arziydi. null yoki allaqachon yopilgan deskriptor interfeys hech qachon yaratilmaganini bildiradi, hech qanday istisno ko‘rinmasa ham. builder dagi interfeys nomini tizim faol VPN uchun aytadigan nom bilan solishtiring, sinov qurilmasida dumpsys ishlatib. Agar ular farq qilsa, siz qurgan tunnel trafikni tashiyotgan tunnel emas.

adb shell dumpsys connectivity

Xuddi shu nomuvofiqlik ulangan belgini o‘lik trafik bilan izohlaydi. Tizim boshqa dasturning tunnelini ko‘rsatadi, kodingiz esa o‘ziniki bo‘lmagan interfeys deskriptorini ushlab turadi.

Qadam 3: connect dan oldin protect ni chaqiring

Interfeys paydo bo‘lgach, dasturingiz ochadigan soketlar sukut bo‘yicha tunnelga yo‘naltiriladi. Tashqi transport bu qoidaga amal qila olmaydi, aks holda qadoqlangan paket interfeysga qaytib tushadi, shuning uchun VpnService protect soketni VPN ni chetlab o‘tib, ostidagi tarmoqdan foydalanish uchun belgilaydi. Chaqiruv boolean qaytaradi, va uni e’tiborsiz qoldirish sog‘lom ko‘rinadigan, ammo hech narsa tashimaydigan soketga olib keladigan yo‘ldir.

protect ni connect yoki bind dan oldin chaqiring, hech qachon keyin emas. Himoya soket ulanmasdan oldin joyida bo‘lishi kerak, chunki ulangan soket yo‘lini allaqachon tanlagan va keyingi protect uni ishonchli ko‘chirmaydi. Agar protect false qaytarsa, to‘xtang va egalikni qayta tekshiring: interfeys dasturingizga tegishli bo‘lmaganda ishlamaydi, va bu aynan boshqa VPN qoldiradigan holat. false qaytishi 1-qadamga qaytish signali, xuddi shu soketni qayta sinash emas.

DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
    return;
}
socket.connect(serverAddress, serverPort);

Qadam 4: soket noqulay bo‘lganda jarayonni bog‘lang

Ba’zi transportlar bitta soket emas: kutubxona bir nechtasini ochishi mumkin yoki yordamchi jarayondagi har bir ulanish bir xil chiqishdan foydalanishini xohlashingiz mumkin. ConnectivityManager.bindProcessToNetwork jarayonni tanlangan tarmoqqa bog‘laydi, eski setProcessDefaultNetwork esa eskirishidan oldin xuddi shu ishni qilgan. Ostidagi ulanishni NET_CAPABILITY_NOT_VPN bilan so‘rang, bog‘lash tunnellingiz ostidagi tarmoqni tanlasin, tunnelning o‘zini emas.

NetworkRequest request = new NetworkRequest.Builder()
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    .build();

Jarayonni bog‘lash ikkinchi VPN emas. U o‘sha jarayon uchun chiqish tanlaydi, bu sizning transportingizga foydali va bir vaqtda ikki tunnel yurgizishga foydasiz.

Kod yo‘lini emas, foydalanuvchi qurilmasini tuzating

Ikki dasturga VPN o‘rnini bo‘lishishga ruxsat beradigan API yo‘q, shuning uchun tuzatish qurilma holatiga tegishli. Foydalanuvchiga ikki aniq yo‘l taklif qiling: boshqa dastur ulanishini uzing yoki uning doim yoniq sozlamasini o‘chiring, shunda prepare ingiz egallashi mumkin, yoki o‘sha dasturning dastur bo‘yicha sozlamalarini ochib, dasturingizni uning tunnelidan chiqarib tashlang. Istisno qolgan hamma narsa uchun filtrni ishlab turadi va dasturingizga oddiy ulanishdan foydalanish imkonini beradi, bu ko‘pincha foydalanuvchi haqiqatan xohlagan natija.

Ikki yo‘lni qo‘llab-quvvatlash hujjatlaringizga yozing, chunki foydalanuvchilar qaysi dastur VPN ga egalik qilishini kamdan-kam biladi. Ulardan Sozlamalardan faol VPN nomini va jurnallaringizdan prepare, establish va protect natijalarini yuborishni so‘rang, bir daqiqada qaysi qadam ishlamaganini aytib bera olasiz. So‘ng haqiqiy trafik bilan tekshiring: nom qidiruvi, TCP ulanishi va tunnel orqali bitta so‘rov, faqat ulangan belgi emas. Haqiqiy deskriptor va yashil ko‘rsatkich ko‘pi bilan egalikni isbotlaydi, transportning marshrutlash qoidalaridan omon qolganini hech qachon emas.

Agar to‘rttala tekshiruv o‘tsa va trafik baribir o‘lsa, egalik endi sizning muammoingiz emas. Marshrutlash va serverga yetib borishga o‘ting, bir xil hisob ma’lumotlarini VPN dasturi o‘rnatilmagan qurilmadan sinab ko‘ring.

O'xshash maqolalar