Android-in VpnService xidmətində çıxarma marşrutu yoxdur və API oxumağın heç bir miqdarı onu yaratmayacaq. Builder.addRoute() tunelə yalnız təyinatlar əlavə edir, ona görə bir LAN seqmentini yerli saxlamaq o seqmentin marşrut siyahısına heç vaxt daxil olmaması deməkdir. Əvəzində əlavə etdiyiniz seqmentin tamamlayıcısıdır, adi prefikslərlə ifadə olunur. İş hesablamadır və bir neçə proqnozlaşdırıla bilən yerdə uğursuz olur.

Aşağıdaki yoxlamaları sıra ilə keçin. Hər biri əvvəlkinin keçdiyini fərz edir, ona görə simptomları aşağıda yamaq əvəzinə ilk uğursuzluqda dayanın.

Tunelin iddia etdiyindən başlayın

0.0.0.0/0-i addRoute()-ə ötürmək Android-ə bildirir ki, hər IPv4 təyinatı tunelə aiddir. Buna görə bu qədər müştəri bölünmüş tunel qabiliyyətsiz görünür: tam ünvan məkanını iddia edir, sonra ondan çıxmağa çalışır. Qurucuda heç nə çıxmır. Yerli saxlamaq istədiyiniz şəbəkə üçün daha dəqiq marşrut insanların gözlədiyinin əksini edir, çünki ən uzun uyğun prefiks qalib gəlir və həmin şəbəkə tunelin içində qalır.

Marşrut siyahısı bütün siyasətdir. Onun arxasında hər təyinat üçün veto yoxdur və Builder sənədi belə bir metod sadalamır.

Tamamlayıcını prefiks hesabından yaradın

Çıxarılmış prefiksin tamamlayıcısı ünvan ağacının kökünə gedən yolda qardaşlarının çoxluğudur. 1-dən çıxarılmış uzunluğa qədər hər uzunluq üçün prefiksinizi ehtiva edən həmin uzunluqdaki bloku götürün, prefiksin dərhal altındaki biti çevirin və nəticəni verin. Çalışdırmayana qədər mücərrəd səslənir.

10.0.0.0/8-ü çıxarmaq səkkiz marşrut verir: 128.0.0.0/1, 64.0.0.0/2, 32.0.0.0/3, 16.0.0.0/4, 0.0.0.0/5, 12.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8. Heç biri 10.0.0.0/8-ü ehtiva etmir və birlikdə qalan hər şeyi əhatə edir.

Səkkiz sətir hər hansı prefiks üçün həmin siyahını yaradır:

import ipaddress
def complement(addr, length):
    base = int(ipaddress.IPv4Address(addr))
    out = []
    for k in range(1, length + 1):
        block = base & (0xFFFFFFFF << (32 - k))
        sibling = block ^ (1 << (32 - k))
        out.append(f"{ipaddress.IPv4Address(sibling)}/{k}")
    return out
print(complement("10.0.0.0", 8))

Marşrut sayı prefiks uzunluğuna bərabərdir və izlənməli olan rəqəm budur. Tək /21 çıxarma 21 marşruta başa gəlir və oxunaqlı qalır. On çıxarma bir neçə yüzə başa gələ bilər, bu da adətən generatorun deyil, şəbəkə dizaynının dəyişməli olduğunu bildirir.

Ünvan ailəsini və tunelin əhatəsini yoxlayın

IPv4 marşrutları IPv6 üçün heç nə etmir. Tunel IPv6 ünvanı iddia edirsə, IPv6 LAN prefiksi 128 bit üzərində eyni hesabla yaradılmış öz tamamlayıcısına ehtiyac duyur. Çıxarmanın kağızda işləməsinin, yerli cihazın isə əlçatmaz qalmasının geniş yayılmış səbəbi budur: hosta IPv6 ilə çatıldı və yalnız IPv4 kənara çıxarılmışdı. Riyaziyyatın səhv olduğu qənaətinə gəlməzdən əvvəl hər iki ailəni yoxlayın.

Əhatə yoxlamanın digər yarısıdır. Android marşrutlamanı şəbəkə və tətbiq üzrə izləyir, ona görə eyni prefiks VPN-in necə elan edildiyindən asılı olaraq bir tətbiq üçün tuneldən, digəri üçün birbaşa ola bilər.

DNS və tətbiq qaydalarını yerinə qoyun

Marşrut çıxarmaları həlledici proqramı dəyişmir. Yerli host adı hələ də tunelin DNS serveri tərəfindən cavablandırıla bilər, halbuki ünvanı yerli marşrutlanır və uyğunsuzluq adın LAN-ın çata bilmədiyi bir şeyə həll olunması kimi görünür. Həlledici siyasətini qəsdən qurun, axtarış domeni və ya bölünmüş DNS qaydası ilə. Marşrutların bunu sizin üçün qərara aldığını fərz etməyin.

addDisallowedApplication() bir tətbiqi tuneldən kənarda saxlayır; içəridə qalan tətbiqlər üçün təyinatı kənarda saxlamır. protect() açdığınız soketin tuneli yan keçməsinə imkan verir, tunel öz nəqliyyatını tutmaqdan belə yayınır. Heç biri tamamlayıcını əvəz etmir.

Öz siyahınızla deyil, axtarışla doğrulayın

Tunel qalxdıqdan sonra qurduğunuz siyahını yenidən oxumaq əvəzinə cihazdan soruşun ki, ünvan həqiqətən hara gedir. iproute2 ilə gələn quruluşda adb shell ip route get 10.1.2.3 kernelin seçdiyi interfeysi adlandırır. Eyni əmri ictimai ünvan üçün işlədin və tuneli adlandırdığını təsdiqləyin.

Daha iki yoxlama dövrəni bağlayır. Əvvəlcə yerli adı həll edin, sonra həll olunmuş ünvanda adb shell ip route get işlədin və tunel olmayan interfeys tələb edin, çünki uğurlu adb shell ping -c 1 host.lan çatımlılığı sübut edir, yolu deyil. Tunel IPv6 iddia edirsə, ünvan ailəsi testini təkrarlayın. Göndərdiyiniz API səviyyəsində test edin, çünki VPN şəbəkələrinin marşrut cədvəlinə necə çıxarıldığı buraxılışlar boyu dəyişib. Kağızda düzgün görünən marşrut siyahısı və yanlış interfeysi seçən axtarış fərqli xətalardır və yalnız ikincisi istifadəçilərə çatır.

Çıxarma siyahısı böyüməyə davam edirsə, marşrut yaratmağı dayandırın və uzaq şəbəkəni yenidən nömrələyin ya da tuneli daraldın. Generator itkin API üçün müvəqqəti həlldir, dizayn aləti deyil.

Əlaqəli məqalələr