Android VpnService-də split tunneling: əslində nəyi marşrutlaşdırmaq olar
VpnService yalnız builder-in öz deskriptoruna göndərdiyi paketləri ötürür. Split tunneling-i günahlandırmadan əvvəl prefiksləri, proxy autentifikasiyasını, DNS-i və tətbiq siyahılarını yoxlayın.
VpnService tətbiqində split tunneling bir neçə konkret yerdə pozulur və hər biri üçün təmir fərqlidir. Müştəri yalnız uğursuz olan bir təyinat göstərir, ona görə ilk iş hansı sərhədə dəydiyinizi müəyyən etməkdir: builder-in aldığı marşrutlar, autentifikasiya edə bilmədiyiniz proxy, yalnız elan etdiyiniz resolver və ya platformanın hər istifadəçi üzrə tətbiq etdiyi tətbiq siyahısı. Məhz buna görə dörd addımlıq yoxlama saxlayıram. O, aşağıdakı qaydada işləyir və ilk uğursuzluqda dayanır.
Builder-in platformaya nə verdiyini təsdiqləyin
VpnService.Builder bəyannamələr siyahısıdır. establish() virtual interfeys üçün ParcelFileDescriptor qaytarır və platforma yalnız addAddress və addRoute prefikslərinə uyğun trafiki həmin deskriptora göndərir; addDnsServer müştərilərə hansı resolverə müraciət edəcəyini bildirir. Əlavə etdiyiniz bütün prefikslərdən kənarda qalan təyinat heç vaxt tətbiqinizə çatmır, interfeys nə vəd etsə də. Bu tək fakt kod dəyişikliyindən əvvəl pozulmuş split tunneling barədə şikayətlərin çoxunu izah edir.
Builder-inizin yığdığı ünvan, marşrut və DNS siyahılarını loqa yazın, sonra onları uğursuz olan təyinatla müqayisə edin. İdarəetmə hostu üçün çatışmayan bir /32 pozulmuş tuneldən qat-qat çox rast gəlinir. Siyahı düzdürsə, davam edin; səhvdirsə, yoxlama siyahısının qalanı boş yerə sərf olunan səydir.
excludeRoute yalnız API 33-dən mövcuddur
Təyinat əsaslı istisna ən çox dəstək müzakirəsinə çevrilən tələbdir. builder.excludeRoute(IpPrefix) API 33-də gəldi; ondan əvvəl yeganə dəstəklənən yaxınlaşma istisna edilən prefiksə qədər hər şey üçün marşrut əlavə etməkdir, yəni tamamlayıcı prefiksləri özünüz hesablamalısınız. Bu iki çağırış güzgü əksi deyil: biri interfeys marşrut dəstindən çıxır, digəri dəsti sıfırdan qurur və köhnə cihaz tanımadığı çağırışı atacaq və ya səssizcə nəzərə almayacaq. Build.VERSION.SDK_INT üzrə budaqlanın və hər iki yolu real avadanlıqda sınayın.
Tamamlayıcıları hesablayarkən prefiks düzülüşünə diqqət edin. /16 marşrutu daxilində /24 istisna qalan hissəni həqiqətən təsvir edən örtücü prefikslər tələb edir, bir səhv formalaşdırılmış /8 yox. Yekun siyahını loqa yazın və istisna edilən hostun hələ də tuneldən kənar yolla həll olunduğunu təsdiqləyin.
Proxy etimad məlumatlarını ifadə etmək mümkün deyil
setHttpProxy(ProxyInfo) interfeysi HTTP və ya SOCKS proxy-yə yönəldir və PAC URL hər təyinat üzrə onların arasında seçim edə bilər. Nə ProxyInfo, nə də PAC formatı istifadəçi adı və parol daşımır, ona görə autentifikasiyalı proxy platforma API-sindən kənarda qalır. Buna ehtiyacı olan tətbiqlər adətən istifadəçi məkanı stack-i, tun2socks və ya oxşar mühərrik yerləşdirir və 407 sorğusuna özləri cavab verir.
Bu seçimin nəticələri var. İstifadəçi məkanı stack-i yalnız ona yönəltdiyiniz trafiki görür, ona görə eyni deskriptor sərhədində yaşamalıdır və öz yuxarı kanal soketi üçün eyni protect() tələbini miras alır. protect()-i atlayın və tunel öz transportunu tutur, bu da ilk paketdən sonra donan əl sıxışması kimi görünür. Etimad məlumatı tələb edən proxy-yə qarşı sınayın, çünki açıq proxy platforma yolunda keçir və heç nə sübut etmir.
Tətbiq siyahıları və DNS də bəyannamədir
Builder-də həm addAllowedApplication, həm də addDisallowedApplication var və onlar bir-birini istisna edir: ikisini çağırmaq xəta atır. Hər halda siyahı interfeys qurularkən hər istifadəçi üzrə tətbiq olunur, ona görə iş profili tətbiqi sizin tunelinizlə deyil, iş profili tuneli ilə idarə olunur. Heç bir API sizə başqa tətbiqin qərarına nəzarət vermir: paketi kənardan tunelinizə məcbur edə bilməzsiniz və artıq aktiv olan VPN-i bağlaya və ya yenidən konfiqurasiya edə bilməzsiniz.
DNS də eyni naxışı izləyir. addDnsServer resolver ünvanını elan edir; tətbiqinizin sorğulara cavab verməsinə imkan vermir. Adları özünüz həll etmək istəyirsinizsə, resolver işə salın və ünvanını tunelə yönəldin. Sabit host adına DoT və ya DoH istifadə edən tətbiqlər elan etdiyiniz ünvanı yan keçə bilər, ona görə sorğu yolunu da tutmadığınız müddətcə ad həllini ən yaxşı səy kimi qəbul edin.
Manifest, always-on və dörd addımlı test
Uyğunluq manifestdə bəyan edilir: BIND_VPN_SERVICE, android.net.VpnService intent filtri və tunel fonda qalmalıdırsa, foreground xidməti. Always-on VPN əlavə olaraq təmiz onRevoke tələb edir, çünki sistem onu istifadəçi parametrləri dəyişəndə və ya başqa tətbiq nəzarəti ələ keçirəndə çağırır.
Yoxlamaları sıra ilə aparın və ilk uğursuzluqda dayanın. Birinci, builder-ə verilən ünvan, marşrut və DNS siyahılarını çıxarın. İkinci, establish()-in deskriptor qaytardığını və transport soketinin qorunduğunu təsdiqləyin. Üçüncü, daxil edilmiş prefiks daxilində bir və istisna edilmiş prefiks daxilində bir təyinat sorğulayın. Dördüncü, yalnız sizin resolverinizin həll edə biləcəyi host adını sorğulayaraq hansı resolverin faktiki cavab verdiyini yoxlayın.
Tamamlanmış əl sıxışması sonrakı addımların heç birini sübut etmir. Hər yoxlama bir qatı təcrid edir, ona görə ikinci addımdakı keçid dördüncü addım barədə heç nə demir.
VpnService.Builder sənədi builder-in tam səthini sadalayır. Bundan əlavə ehtiyac duyduğunuz hər şey başqa API, başqa tətbiq və ya öz istifadəçi məkanı stack-inizdir və bu, split-tunnel xətası deyil, dizayn qərarıdır.