Nega Android VpnService trafikning bir qismini ushlaydi, hammasini emas
Yo'llar, DNS yozuvlari va har bir ilova bo'yicha qamrov qaysi paketlar tun qurilmasiga yetib borishini, mahalliy qurilmalar nega yo'qolishini va quruvchi nimadan bosh tortishini belgilaydi.
VpnService ichida hech narsa trafikni o'z-o'zidan ushlamaydi. U tizimdan tun interfeysini so'raydi, o'sha interfeysga manzillar va yo'llar to'plamini beradi, va shu paytdan boshlab yadro o'sha yo'llarga mos har bir paketni ilova o'qiy oladigan fayl deskriptoriga ko'chiradi. Ilova kodi yo'llar tanlamagan paketlarni hech qachon ko'rmaydi, shuning uchun tunnel qamrovi dasturlash savoli bo'lishidan oldin marshrutlash jadvali savolidir. Shu sababli bir xil xizmat amalga oshirilishi bitta telefonda butun oqimni yutib yuborishi, boshqasida esa faqat bir qismini, va shu sababli yo'l qo'shish ba'zan buzilgan ko'ringan tunnelni tuzatadi. Siz olgan narsa e'lon qilganingizdir, quruvchi jimgina rad etgan hamma narsani ayirib tashlaganda.
Qaysi paketlar kelishini yo'llar belgilaydi
Builder.addRoute(prefix, prefixLength) VPN tarmog'ining marshrutlash jadvaliga prefiks o'rnatadi. Tizim ushbu tarmoqni qamrovdagi ilovalar uchun standart deb hisoblaydi, shuning uchun uning yozuvlari jismoniy tarmoqning standart yo'lidan oldin ko'riladi va mos prefiks oqimni burish uchun yetarli. Shu sababli 0.0.0.0/0 uchun yo'l IPv4 ni to'liq oladi, printer, cast nishoni va marshrutizatorning boshqaruv sahifasi bilan birga.
Jismoniy standart yozuvni o'chirmasdan shu qamrovni istagan mijozlar buning o'rniga 0.0.0.0/1 va 128.0.0.0/1 juftidan foydalanadi. Ikki aniqroq yo'l standart yo'lni yengadi, birgalikda ular butun manzil fazosini qoplaydi, va telefonning o'z standart yozuvi hanuz jismoniy tarmoqqa bog'langan soketlar uchun jadvalda qoladi.
Manzillar va DNS yozuvlari bir xil quruvchidan keladi va boshqa savolga javob beradi. addAddress interfeysga prefiks uzunligi bilan manzil beradi, addDnsServer esa qamrovdagi ilovalar interfeys orqali so'raydigan hal qiluvchini o'rnatadi. Ikki oila ham bitta interfeysda o'tirishi mumkin, shuning uchun faqat IPv4 yo'llar to'plami IPv6 manzili yonida to'g'ri o'qiladigan va baribir oqib ketadigan konfiguratsiya. Agar interfeysda manzili yo'q oilani marshrutlasangiz, yadroda bu paketlar uchun manba manzili bo'lmaydi va ular deskriptorda hech qachon ko'rinmaydi.
establish() nima qaytaradi
establish() ParcelFileDescriptor qaytaradi, yoki ilova ruxsat etilmaganida null. null tarmoq xatosi emas, rozilik holati: VpnService.prepare() allaqachon null qaytargan bo'lishi kerak, yoki foydalanuvchi chaqiruvdan oldin tizim muloqotini tasdiqlagan bo'lishi kerak. Rozilik xizmat ishlayotganda qaytarib olinishi mumkin, va interfeys sizning o'qish siklingizga hech qanday qayta chaqiruvsiz oyog'ingiz ostida yopiladi.
Agar boshqacha aytmasangiz, deskriptor bloklamaydi, shuning uchun o'qish ipni to'xtatib qo'yish o'rniga ma'lumotsiz darhol qaytadi. Bloklovchi soket uchun yozilgan sikl bitta yadroni yoqib yuboradi, bo'sh o'qishni halokatli deb hisoblaydigan sikl esa bo'sh soniyada tunnelni yirtib tashlaydi. Builder.setBlocking(true) bu xatti-harakatni o'zgartiradi, va narx o'qish ichida kutadigan ip.
Yo'l va manzil argumentlari LinkAddress qiymatlari sifatida tekshiriladi, 224.0.0.0/4 kabi multicast manzillari esa darhol rad etiladi. Nuqta-nuqtaga tun interfeysi ham translyatsiya domeniga ega emas, shuning uchun u orqali multicast topish uchun yana bitta yo'l emas, boshqa dizayn kerak. Tekshiriladigan ro'yxat VpnService.Builder bo'lib, chaqiruv e'tiborsiz qoldirilgan degan xulosaga kelishdan oldin.
Ilova bo'yicha qamrov to'plamni toraytiradi, tunnelni emas
API 21 dan boshlab quruvchi addAllowedApplication va addDisallowedApplication ni qabul qiladi, va ikkala ro'yxat bitta quruvchi ichida bir-birini istisno qiladi. Ruxsat ro'yxati o'sha paketlar uchun tunnelni mavjud qiladi, qolgan hamma narsa jismoniy tarmoqni saqlaydi; taqiq ro'yxati nomlangan paketlardan boshqa hamma narsani ushlaydi, mijoz buni bo'lingan tunnellash sifatida taklif qiladi. API 21 gacha platforma mexanizmi umuman yo'q, va ilova bo'yicha xatti-harakat o'z yo'naltirgichida UID bo'yicha filtrlaydigan uchinchi tomon mijozlaridan kelgan. Bu farq disk raskadrovkada muhim, chunki bitta paketli ruxsat ro'yxatiga ega ilova bo'yicha tunnel deyarli trafik hosil qilmaydi va bu to'g'ri xatti-harakat, buzilgan yo'l emas.
Qamrov qanday bo'lishidan qat'i nazar, ilovangiz VPN serveriga ochadigan soket o'zi qurayotgan tunneldan o'tmasligi kerak. VpnService.protect(socket) o'sha soketni ostidagi tarmoqqa bog'laydi, shunda uning paketlari tun qurilmasini chetlab o'tadi. Agar chaqiruvni o'tkazib yuborsangiz, qo'l berishni uni ko'tarishi kerak bo'lgan interfeys yutib yuboradi.
VpnService.setUnderlyingNetworks tizimga tunnelni qaysi jismoniy tarmoq ko'tarayotganini aytib, aylanani yopadi. Bu qiymat VPN boshqa ilovalarga ulanish haqida qanday xabar berishini belgilaydi, va null yoki eskirgan qiymat telefonning qolgan qismi oflayn deb hisoblaydigan ulangan tunnelning odatiy sababi. Uni ostidagi tarmoq o'zgarganda yangilang, faqat ishga tushirishda emas.
Tekshiruv summalari va MTU: to'g'ri yo'l ham muvaffaqiyatsiz bo'ladigan joy
Paketlar kelgandan so'ng, paket darajasidagi ikki tafsilot biror narsa boshdan oxirigacha ishlashini belgilaydi. Birinchisi manba manzili: bir nechta interfeys manzili bilan yadro birinchisini ko'targan paketlarni yuborishi mumkin, shuning uchun sarlavhalarni qayta yozadigan yo'naltirgich manzilni va uni qoplaydigan tekshiruv summasini tuzatishi kerak.
Ikkinchisi tekshiruv summasining qamrovi. Ilova TCP yoki UDP paketlarini o'zi qursa, tekshiruv summasi manba manzili, manzil manzili, protokol raqami va transport uzunligini saqlaydigan soxta sarlavhani qoplaydi, va ulardan birini tashlab ketish kelib tashlanadigan paketlar beradi. Bu muvaffaqiyatsizlik hech qachon kelmaydigan javobdan keyingi taym-aut kabi ko'rinadi, va bu ko'pchilikni yo'llarga qaytaradi. setMtu interfeys MTU sini belgilaydi, va har bir o'qish aynan bitta to'liq IP paketini qaytaradi, shuning uchun bayt oqimi uchun yozilgan bufer paketni emas, tahlilingizni bo'laklaydi.
Qatlamlarni ajratadigan tekshiruv davrasi
Qamrov qayerda xato ketganini topish uchun qatlamlarni tartib bilan sinab ko'ring. Qurilmadan VPN tarmog'i haqiqatda qaysi yo'llarni tutishini so'rang, so'ng ma'lum manzilga oqim deskriptorda o'qish sifatida ko'rinishini tekshiring, so'ng yo'naltirgichingiz yuboradigan paket yaxshi shakllanganini tekshiring. Yo'l muammosi deskriptorda hech narsa ko'rsatmaydi, tekshiruv summasi muammosi esa kelib g'oyib bo'ladigan paketni ko'rsatadi.
Agar deskriptorga hech narsa yetib bormasa, gumondor o'quvchi emas, yo'llar to'plami: prefikslarni tasdiqlang, o'sha oilada manzil borligini tasdiqlang va ilova siz belgilagan qamrov ichida ekanini tasdiqlang. Agar paketlar deskriptorga yetib borsa, lekin hech narsa qaytmasa, yana yo'lga tegishdan oldin protect() va ostidagi tarmoq qiymatini tekshiring. Agar uzoq tomon buzilgan paketlar haqida xabar bersa, tekshiruv summasi va MTU qarash kerak bo'lgan joylar. Har bir qatlamga bitta tekshiruv yarim kunlik taxminni tejaydi.