Android syn VpnService hat gjin útslutingsrûte, en gjin hoemannichte API-lêzen sil der ien produsearje. Builder.addRoute() foeget altiten allinnich bestimmingen ta oan de tunnel, dus in LAN-segment lokaal hâlde betsjut dat dat segment nea yn de rûtelist komt. Wat jo ynstee tafoegje is it komplement fan it segment, útdrukt yn gewoane prefigs. It wurk is rekkenjen, en it mislearret op in hantsjefol foarsisbere plakken.

Wurkje de checks hjirûnder yn oarder troch. Elk giet derfan út dat de foarige hold, dus stopje by de earste mislearring ynstee fan symptomen fierderop te patches.

Begjin by wat de tunnel beweart

0.0.0.0/0 oan addRoute() jaan fertelt Android dat elke IPv4-bestimming by de tunnel heart. Dêrom lykje safolle kliïnten net by steat ta split-tunneling: se beweare de folsleine adresromte en besykje der dan fan ôf te lûken. Neat yn 'e bouwer lûkt ôf. In spesifiker rûte foar it netwurk dat jo lokaal hâlde woene docht it tsjinoerstelde fan wat minsken ferwachtsje, want it langste oerienkommende prefigs wint en dat netwurk bedarret yn 'e tunnel.

De rûtelist is it hiele belied. D'r is gjin feto per bestimming efter, en de Builder-referinsje neamt gjin metoade dy't der ien leverje soe.

Generearje it komplement út prefigs-rekkenjen

It komplement fan in útsletten prefigs is de set fan syn bruorren op it paad nei de woartel fan 'e adresbeam. Nim foar elke lingte fan 1 oant de útsletten lingte it blok fan dy lingte dat jo prefigs befettet, draai it bit fuort ûnder it prefigs en jou it resultaat út. It klinkt abstrakt oant jo it rinne litte.

It útsluten fan 10.0.0.0/8 jout acht rûtes: 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. Gjinien fan har befettet 10.0.0.0/8, en tegearre dekke se al it oare.

Acht rigels generearje dy list foar elk prefigs:

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

It oantal rûtes is gelyk oan de prefigslingte, en dat is it nûmer om yn 'e gaten te hâlden. Ien inkelde /21-útsluting kostet 21 rûtes en bliuwt lêsber. Tsien útslutings kinne in pear hûndert kostje, wat meastentiids betsjut dat it netwurkûntwerp feroare wurde moat en net de generator.

Kontrolearje de adresfamylje en it berik fan 'e tunnel

IPv4-rûtes dogge neat foar IPv6. As de tunnel in IPv6-adres beweart, hat in IPv6-LAN-prefigs syn eigen komplement nedich, generearre mei deselde rekkenjen oer 128 bits. In faak foarkommende oarsaak dat de útsluting op papier wurket wylst it lokale apparaat ûnberikber bliuwt is dit: de host waard berikt oer IPv6, en allinnich IPv4 wie útsneden. Kontrolearje beide famyljes foardat jo konkludearje dat de wiskunde ferkeard is.

Berik is de oare helte fan 'e check. Android folget routing per netwurk en per app, dus itselde prefigs kin foar ien app troch de tunnel gean en foar in oare direkt, ôfhinklik fan hoe't de VPN ferklearre is.

Set DNS- en per-app-regels dêr't se hearre

Rûte-útslutings feroarje de resolver net. In lokale hostnamme kin noch altyd beantwurde wurde troch de DNS-tsjinner fan 'e tunnel wylst syn adres lokaal rûte wurdt, en de mismatch docht bliken as in namme dy't oplost nei eat dat it LAN net berikke kin. Stel it resolverbelied bewust yn, mei in sykdomein of in split-DNS-regel. Nim net oan dat de rûtes it foar jo besletten hawwe.

addDisallowedApplication() hâldt ien app bûten de tunnel; it hâldt gjin bestimming bûten foar de apps dy't binnen bliuwe. protect() lit in socket dy't jo iepenje de tunnel omgean, en sa foarkomt in tunnel dat er syn eigen ferfier fangt. Gjin fan beide ferfangt it komplement.

Ferifiearje mei in sykopdracht, net mei jo eigen list

As de tunnel ienris omheech is, freegje it apparaat wêr't in adres eins hinne giet ynstee fan de list dy't jo boud hawwe op 'e nij te lêzen. Op in build dy't iproute2 leveret, neamt adb shell ip route get 10.1.2.3 de ynterface dy't de kernel keas. Rin itselde kommando foar in iepenbier adres en befêstigje dat it de tunnel neamt.

Twa checks mear slute de lus. Los earst in lokale namme op, rin dan adb shell ip route get op it oploste adres en easkje in ynterface dy't net de tunnel is, want in slagge adb shell ping -c 1 host.lan bewiist berikberens en net it paad. Werhelje de adresfamyljetest oer IPv6 as de tunnel der ien beweart. Test op it API-nivo dat jo leverje, want hoe't VPN-netwurken oan 'e routingtabel bleatsteld wurde is oer releases hinne feroare. In rûtelist dy't op papier goed liket en in sykopdracht dy't de ferkearde ynterface kiest binne ferskillende bugs, en allinnich de twadde berikt brûkers.

As de útslutingslist stadich groeit, stopje dan mei rûtes generearjen en nûmerje it fiere netwurk op 'e nij of fersmelle de tunnel ynstee. De generator is in omwei foar de ûntbrekkende API, gjin ûntwerpgereid.

Relatearre artikelen