Android VPN туннелінен ішкі желіні қалай шығару керек
VpnService маршрутты шығара алмайды, сондықтан қосымшаны қосасыз: /8 үшін сегіз құрылған префикс, сонымен қатар қалғанын ұстайтын IPv6, DNS және іздеу тексерулері.
Android-тың VpnService қызметінде шығару маршруты жоқ, және API оқудың қандай да бір мөлшері оны жасамайды. Builder.addRoute() туннельге тек тағайындауларды қосады, сондықтан LAN сегментін жергілікті ұстау дегеніміз сол сегменттің маршруттар тізіміне мүлдем кірмейтіні. Оның орнына сіз сегменттің қосымшасын қосасыз, ол кәдімгі префикстермен өрнектеледі. Жұмыс арифметика, және ол бірнеше болжауға болатын жерде сәтсіз аяқталады.
Төмендегі тексерулерді ретімен орындаңыз. Әрқайсысы алдыңғысы орындалды деп есептейді, сондықтан төмендегі симптомдарды жамаудың орнына бірінші сәтсіздікте тоқтаңыз.
Туннель не талап ететінінен бастаңыз
0.0.0.0/0-ді addRoute()-ге беру Android-ке әрбір IPv4 тағайындауы туннельге тиесілі екенін айтады. Сондықтан көптеген клиенттер бөлінген туннельдеуге қабілетсіз болып көрінеді: олар бүкіл адрестік кеңістікті талап етіп, содан кейін одан шегеруге тырысады. Құрастырушыда ештеңе шегермейді. Жергілікті қалдырғыңыз келген желі үшін нақтырақ маршрут адамдар күткеннің керісінше әрекет етеді, өйткені ең ұзын сәйкес префикс жеңеді және сол желі туннельдің ішіне түседі.
Маршруттар тізімі — бүкіл саясат. Оның артында әр тағайындауға вето жоқ, және Builder анықтамасы мұндай әдісті тізімдемейді.
Қосымшаны префикс арифметикасынан құрыңыз
Шығарылған префикстің қосымшасы — адрестер ағашының тамырына барар жолдағы оның ағайындыларының жиыны. 1-ден шығарылған ұзындыққа дейінгі әр ұзындық үшін префиксіңізді қамтитын сол ұзындықтағы блокты алыңыз, префикстің дәл астындағы битті аударыңыз және нәтижені шығарыңыз. Оны іске қоспайынша бұл дерексіз естіледі.
10.0.0.0/8-ті шығару сегіз маршрут береді: 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. Олардың ешқайсысы 10.0.0.0/8-ні қамтымайды, ал бірге олар қалғанының бәрін жабады.
Сегіз жол кез келген префикс үшін сол тізімді құрады:
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))
Маршруттар саны префикс ұзындығына тең, және бұл бақылау керек сан. Бір /21 шығару 21 маршрутқа тұрады және оқылымды болып қалады. Он шығару бірнеше жүзге тұруы мүмкін, бұл әдетте генераторды емес, желі дизайнын өзгерту керек екенін білдіреді.
Адрестер тобын және туннель ауқымын тексеріңіз
IPv4 маршруттары IPv6 үшін ештеңе істемейді. Егер туннель IPv6 адресін талап етсе, IPv6 LAN префиксіне өзінің қосымшасы қажет, ол 128 бит бойынша сол арифметикамен құрылады. Шығару қағазда жұмыс істеп, жергілікті құрылғы қолжетімсіз болып қалуының жиі себебі мынау: хостқа IPv6 арқылы жетті, ал тек IPv4 қиылып алынды. Арифметика қате деген қорытындыға келмес бұрын екі топты да тексеріңіз.
Ауқым — тексерудің екінші жартысы. Android маршруттауды желі бойынша және қолданба бойынша бақылайды, сондықтан бір префикс VPN қалай жарияланғанына қарай бір қолданба үшін туннельден, екіншісі үшін тікелей өтуі мүмкін.
DNS және қолданба бойынша ережелерді тиісті орнына қойыңыз
Маршрутты шығару шешушіні өзгертпейді. Жергілікті хост атауы әлі де туннельдің DNS серверінен жауап алуы мүмкін, оның адресі жергілікті маршрутталады, және сәйкессіздік LAN жете алмайтын нәрсеге шешілетін атау ретінде көрінеді. Шешуші саясатын әдейі орнатыңыз, іздеу домені немесе бөлінген DNS ережесімен. Маршруттар мұны сіз үшін шешті деп ойламаңыз.
addDisallowedApplication() бір қолданбаны туннельден тыс ұстайды; іште қалатын қолданбалар үшін тағайындауды тыс ұстамайды. protect() өзіңіз ашқан сокеттің туннельді айналып өтуіне мүмкіндік береді, осылайша туннель өз тасымалын ұстап қалудан қашады. Екеуі де қосымшаны алмастырмайды.
Өз тізіміңізбен емес, іздеумен тексеріңіз
Туннель көтерілгеннен кейін, құрылған тізімді қайта оқудың орнына құрылғыдан адрестің шын мәнінде қайда баратынын сұраңыз. iproute2 бар құрастыруда adb shell ip route get 10.1.2.3 ядро таңдаған интерфейсті атайды. Сол пәрменді жалпыға ортақ адрес үшін орындап, оның туннельді атайтынын растаңыз.
Тағы екі тексеру циклді жабады. Алдымен жергілікті атауды шешіңіз, содан кейін шешілген адресте adb shell ip route get орындап, туннель емес интерфейсті талап етіңіз, өйткені сәтті adb shell ping -c 1 host.lan қолжетімділікті дәлелдейді, жолды емес. Туннель IPv6 талап етсе, адрестер тобының сынағын сол бойынша қайталаңыз. Өзіңіз шығаратын API деңгейінде сынаңыз, өйткені VPN желілерінің маршруттау кестесіне қалай ұсынылатыны шығарылымдар арасында өзгерді. Қағазда дұрыс көрінетін маршруттар тізімі мен қате интерфейсті таңдайтын іздеу әртүрлі қателер, және пайдаланушыларға тек екіншісі жетеді.
Егер шығару тізімі өсе берсе, маршруттар құруды тоқтатып, қашықтағы желіні қайта нөмірлеңіз немесе оның орнына туннельді тарылтыңыз. Генератор жоқ API үшін айналма жол, дизайн құралы емес.