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-ийн тойрог зам бөгөөд дизайны хэрэгсэл биш.

Холбоотой нийтлэлүүд