VpnService v Androidu nima poti za izločitev in nobena količina branja API-ja je ne ustvari. Builder.addRoute() vedno doda le cilje v tunel, zato ohranjanje segmenta LAN lokalnega pomeni, da ta segment nikoli ne pride na seznam poti. Namesto tega dodate komplement segmenta, izražen z običajnimi predponami. Delo je aritmetika in spodleti na nekaj predvidljivih mestih.

Preverjanja spodaj opravite po vrsti. Vsako predpostavlja, da je prejšnje zdržalo, zato se ustavite ob prvi napaki, namesto da bi nižje krpali simptome.

Začnite s tem, kar tunel zahteva

Posredovanje 0.0.0.0/0 v addRoute() pove Androidu, da vsaka destinacija IPv4 pripada tunelu. Zato se toliko odjemalcev zdi nesposobnih za razdeljeno tuneliranje: zahtevajo celoten naslovni prostor in nato poskušajo od njega odšteti. Nič v graditelju ne odšteva. Bolj specifična pot za omrežje, ki ste ga želeli ohraniti lokalno, deluje nasprotno od pričakovanj, ker zmaga najdaljša ujemajoča se predpona in to omrežje pristane v tunelu.

Seznam poti je celotna politika. Za njim ni veta za posamezno destinacijo in referenca Builder ne navaja nobene metode, ki bi ga zagotovila.

Ustvarite komplement iz aritmetike predpon

Komplement izločene predpone je množica njenih bratov in sester na poti do korena naslovnega drevesa. Za vsako dolžino od 1 do izločene dolžine vzemite blok te dolžine, ki vsebuje vašo predpono, obrnite bit neposredno pod predpono in izpišite rezultat. Zveni abstraktno, dokler tega ne zaženete.

Izločitev 10.0.0.0/8 da osem poti: 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. Nobena od njih ne vsebuje 10.0.0.0/8, skupaj pa pokrivajo vse drugo.

Osem vrstic ustvari ta seznam za katero koli predpono:

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))

Število poti je enako dolžini predpone in to je število, ki ga je treba spremljati. Ena sama izločitev /21 stane 21 poti in ostane berljiva. Deset izločitev lahko stane nekaj sto, kar običajno pomeni, da je treba spremeniti zasnovo omrežja, ne generatorja.

Preverite družino naslovov in obseg tunela

Poti IPv4 ne naredijo nič za IPv6. Če tunel zahteva naslov IPv6, lokalna predpona IPv6 potrebuje svoj komplement, ustvarjen z isto aritmetiko na 128 bitih. Pogost vzrok, da izločitev deluje na papirju, medtem ko lokalna naprava ostane nedosegljiva, je ta: do gostitelja so prišli prek IPv6, izrezan pa je bil le IPv4. Preverite obe družini, preden sklepate, da je matematika napačna.

Obseg je druga polovica preverjanja. Android spremlja usmerjanje po omrežju in po aplikaciji, zato lahko ista predpona gre skozi tunel za eno aplikacijo in neposredno za drugo, odvisno od tega, kako je VPN deklariran.

Pravila DNS in po aplikacijah postavite tja, kamor spadajo

Izločitve poti ne spremenijo razreševalnika. Lokalno ime gostitelja lahko še vedno odgovori strežnik DNS tunela, medtem ko se njegov naslov usmerja lokalno, in neskladje se pokaže kot ime, ki se razreši v nekaj, do česar LAN ne seže. Politiko razreševalnika nastavite namerno, z iskalno domeno ali pravilom razdeljenega DNS. Ne predpostavljajte, da so poti to odločile namesto vas.

addDisallowedApplication() drži eno aplikacijo zunaj tunela; ne drži destinacije zunaj za aplikacije, ki ostanejo znotraj. protect() dovoli vtičnici, ki jo odprete, da obide tunel, in tako se tunel izogne zajetju lastnega prevoza. Nobeno od tega ne nadomesti komplementa.

Preverite s poizvedbo, ne z lastnim seznamom

Ko je tunel vzpostavljen, vprašajte napravo, kam naslov v resnici gre, namesto da bi znova brali seznam, ki ste ga zgradili. Na gradnji, ki prinaša iproute2, adb shell ip route get 10.1.2.3 poimenuje vmesnik, ki ga je izbralo jedro. Zaženite isti ukaz za javni naslov in potrdite, da poimenuje tunel.

Še dve preverjanji skleneta zanko. Najprej razrešite lokalno ime, nato zaženite adb shell ip route get na razrešenem naslovu in zahtevajte vmesnik, ki ni tunel, ker uspešni adb shell ping -c 1 host.lan dokazuje dosegljivost in ne poti. Ponovite preskus družine naslovov prek IPv6, če tunel zahteva eno. Preskusite na ravni API-ja, ki ga dostavljate, ker se je način izpostavljanja omrežij VPN usmerjevalni tabeli med izdajami spreminjal. Seznam poti, ki na papirju izgleda pravilno, in poizvedba, ki izbere napačen vmesnik, sta različni napaki in le druga doseže uporabnike.

Če seznam izločitev še raste, prenehajte ustvarjati poti in preštevilčite oddaljeno omrežje ali namesto tega zožite tunel. Generator je obhod manjkajočega API-ja, ne orodje za načrtovanje.

Sorodni članki