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 үчүн айланма жол, долбоорлоо куралы эмес.