Hogyan zárjunk ki egy alhálózatot az Android VPN-alagútból
A VpnService nem tud útvonalat kizárni, ezért a komplementert adod hozzá: nyolc generált előtag egy /8-hoz, valamint az IPv6-, DNS- és keresési ellenőrzések, amelyek a többit elkapják.
Az Android VpnService-ének nincs kizárási útvonala, és az API olvasása semmilyen mennyiségben nem hoz létre egyet. A Builder.addRoute() mindig csak célpontokat ad az alagúthoz, ezért egy LAN-szegmens helyben tartása azt jelenti, hogy az a szegmens soha nem kerül be az útvonallistába. Amit helyette hozzáadsz, az a szegmens komplementere, közönséges előtagokkal kifejezve. A munka aritmetika, és néhány kiszámítható helyen elbukik.
Az alábbi ellenőrzéseket sorrendben hajtsd végre. Mindegyik feltételezi, hogy az előző tartotta magát, ezért az első hibánál állj meg, ahelyett hogy lejjebb foltoznád a tüneteket.
Kezdd azzal, amit az alagút állít
A 0.0.0.0/0 átadása a addRoute()-nek azt mondja az Androidnak, hogy minden IPv4-cél az alagúthoz tartozik. Ezért tűnik olyan sok kliens képtelennek az osztott alagutazásra: igénylik a teljes címteret, majd megpróbálnak belőle kivonni. A szerkesztőben semmi nem von ki. Egy konkrétabb útvonal ahhoz a hálózathoz, amelyet helyben akartál tartani, az elvárttal ellentétes hatást ad, mert a leghosszabb egyező előtag nyer, és az a hálózat az alagút belsejébe kerül.
Az útvonallista maga a teljes szabályzat. Nincs mögötte célonkénti vétó, és a Builder-referencia nem sorol fel olyan metódust, amely ilyet biztosítana.
Állítsd elő a komplementert előtag-aritmetikával
Egy kizárt előtag komplementere a testvéreinek halmaza a címfa gyökeréhez vezető úton. Minden hosszra 1-től a kizárt hosszig vedd az adott hosszúságú blokkot, amely tartalmazza az előtagodat, fordítsd meg az előtag alatti bitet, és add ki az eredményt. Addig tűnik elvontnak, amíg le nem futtatod.
A 10.0.0.0/8 kizárása nyolc útvonalat ad: 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. Egyik sem tartalmazza a 10.0.0.0/8-t, és együtt minden mást lefednek.
Nyolc sor állítja elő ezt a listát bármely előtaghoz:
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))
Az útvonalak száma megegyezik az előtag hosszával, és ez az a szám, amelyet figyelni kell. Egyetlen /21 kizárás 21 útvonalba kerül, és olvasható marad. Tíz kizárás néhány százba kerülhet, ami általában azt jelenti, hogy a hálózati tervet kell megváltoztatni, nem a generátort.
Ellenőrizd a címcsaládot és az alagút hatókörét
Az IPv4-útvonalak semmit nem tesznek az IPv6-ért. Ha az alagút IPv6-címet igényel, az IPv6 LAN-előtagnak saját komplementerre van szüksége, ugyanazzal az aritmetikával 128 bit felett előállítva. Gyakori oka annak, hogy a kizárás papíron működik, miközben a helyi eszköz elérhetetlen marad, ez: a hosztot IPv6-on keresztül érték el, és csak az IPv4-et vágták ki. Ellenőrizd mindkét családot, mielőtt arra jutsz, hogy a matematika hibás.
A hatókör az ellenőrzés másik fele. Az Android hálózatonként és alkalmazásonként követi az útválasztást, ezért ugyanaz az előtag az egyik alkalmazásnak alagúton mehet, a másiknak közvetlenül, attól függően, hogyan lett a VPN deklarálva.
Tedd a DNS- és alkalmazásonkénti szabályokat oda, ahová tartoznak
Az útvonalkizárások nem változtatják meg a feloldót. Egy helyi hosztnevet továbbra is az alagút DNS-kiszolgálója válaszolhat meg, miközben a címe helyben útválasztódik, és az eltérés úgy jelenik meg, mint egy név, amely olyasmire oldódik fel, amit a LAN nem tud elérni. Állítsd be a feloldó szabályzatát szándékosan, keresési domainnel vagy osztott DNS-szabállyal. Ne feltételezd, hogy az útvonalak döntöttek helyetted.
A addDisallowedApplication() egy alkalmazást kint tart az alagútból; nem tart kint egy célpontot a bent maradó alkalmazások számára. A protect() engedi, hogy a megnyitott socket megkerülje az alagutat, és így az alagút elkerüli a saját forgalmának elkapását. Egyik sem helyettesíti a komplementert.
Kereséssel ellenőrizz, ne a saját listáddal
Amikor az alagút feláll, kérdezd meg az eszközt, hová megy valójában egy cím, ahelyett hogy újraolvasnád az általad épített listát. Egy iproute2-t szállító builden a adb shell ip route get 10.1.2.3 megnevezi a kernel által választott interfészt. Futtasd ugyanezt a parancsot egy nyilvános címre, és igazold, hogy az alagutat nevezi meg.
Két további ellenőrzés zárja a kört. Először oldj fel egy helyi nevet, majd futtasd a adb shell ip route get-et a feloldott címen, és követelj olyan interfészt, amely nem az alagút, mert egy sikeres adb shell ping -c 1 host.lan elérhetőséget bizonyít, nem az útvonalat. Ismételd meg a címcsalád-tesztet IPv6 felett, ha az alagút ilyet igényel. A szállított API-szinten tesztelj, mert az, ahogyan a VPN-hálózatok a forgalomirányítási táblához kerülnek, kiadások között változott. Egy papíron jónak tűnő útvonallista és egy rossz interfészt választó keresés különböző hibák, és csak a második ér el a felhasználókhoz.
Ha a kizárási lista tovább nő, hagyd abba az útvonalak generálását, és számozd újra a távoli hálózatot, vagy szűkítsd az alagutat helyette. A generátor a hiányzó API kerülőútja, nem tervezőeszköz.