A split tunneling egy VpnService-alkalmazásban néhány konkrét helyen törik el, és a javítás mindegyiknél más. A kliens csak egyetlen sikertelen célállomást mutat, ezért az első feladat kideríteni, melyik határba ütközik: a builder által kapott útvonalak, a proxy, amelyet nem tud hitelesíteni, a resolver, amelyet csak bejelentett, vagy az alkalmazáslista, amelyet a platform felhasználónként alkalmaz. Pontosan ezért tartok négy lépéses ellenőrzést. Az alábbi sorrendben fut, és az első hibánál megáll.

Erősítse meg, mit adott a builder a platformnak

A VpnService.Builder deklarációk listája. Az establish() egy ParcelFileDescriptor-t ad vissza egy virtuális interfészhez, és a platform csak az addAddress és addRoute előtagjaival egyező forgalmat küldi ebbe a leíróba; az addDnsServer megmondja a klienseknek, melyik resolverhez forduljanak. Az összes hozzáadott előtagon kívüli cél soha nem ér el az alkalmazásához, bármit ígér az interfész. Ez az egyetlen tény magyarázza a tört split tunnelingről szóló jelentések többségét már kódmódosítás előtt.

Naplózza a builder által összeállított cím-, útvonal- és DNS-listákat, majd hasonlítsa össze őket a sikertelen célokkal. Egy hiányzó /32 egy felügyeleti hoszthoz sokkal gyakoribb, mint egy tört alagút. Ha a lista helyes, lépjen tovább; ha nem, az ellenőrzőlista többi része kárba veszett erőfeszítés.

Az excludeRoute csak API 33-tól létezik

A cél szerinti kizárás az a kérés, amelyből a leggyakrabban támogatási szál lesz. A builder.excludeRoute(IpPrefix) az API 33-ban érkezett; előtte az egyetlen támogatott közelítés az, hogy a kizárt előtagon kívül mindenre útvonalat adunk, ami azt jelenti, hogy a kiegészítő előtagokat magunknak kell kiszámítani. A két hívás nem tükörképe egymásnak: az egyik az interfész útvonalkészletéből von ki, a másik nulláról építi a készletet, és egy régebbi eszköz kivételt dob vagy csendben figyelmen kívül hagy egy általa nem ismert hívást. Ágazzon a Build.VERSION.SDK_INT szerint, és mindkét utat valódi hardveren tesztelje.

A kiegészítők számításakor figyeljen az előtagok igazítására. Egy /24-es kizárás egy /16-os útvonalon belül azokat a lefedő előtagokat igényli, amelyek valóban leírják a maradékot, nem egy hibás /8-at. Naplózza a végleges listát, és ellenőrizze, hogy a kizárt hoszt továbbra is az alagúton kívüli úton oldódik fel.

A proxy hitelesítő adatai nem fejezhetők ki

A setHttpProxy(ProxyInfo) az interfészt HTTP vagy SOCKS proxyra irányítja, és egy PAC URL célonként választhat közöttük. Sem a ProxyInfo, sem a PAC formátum nem hordoz felhasználónevet és jelszót, ezért a hitelesítést igénylő proxy a platform API-ján kívül marad. Az ezt igénylő alkalmazások általában felhasználói térbeli vermet, tun2socksot vagy hasonló motort ágyaznak be, és maguk válaszolnak a 407 kihívásra.

Ennek a döntésnek következményei vannak. A felhasználói térbeli verem csak azt a forgalmat látja, amelyet felé irányít, ezért ugyanazon leíró határain belül kell élnie, és ugyanazt a protect()-követelményt örökli a saját uplink socketjéhez. Ha kihagyja a protect()-et, az alagút elfogja a saját átvitelét, ami az első csomag után megakadó kézfogásként jelenik meg. Olyan proxyval teszteljen, amely hitelesítő adatokat követel, mert a nyitott proxy átmegy a platform útján, és semmit sem bizonyít.

Az alkalmazásonkénti listák és a DNS is deklarációk

A Builderben megtalálható az addAllowedApplication és az addDisallowedApplication is, és ezek kölcsönösen kizárják egymást: mindkettő hívása kivételt dob. Akárhogy is, a listát az interfész beállításakor felhasználónként alkalmazzák, ezért a munkaprofil egyik alkalmazását a munkaprofil alagútja irányítja, nem az öné. Amit egyetlen API sem ad meg, az a másik alkalmazás döntése feletti ellenőrzés: kívülről nem kényszeríthet csomagot az alagútjába, és egy már aktív VPN-t nem zárhat be és nem konfigurálhat át.

A DNS ugyanezt a mintát követi. Az addDnsServer resolver-címet hirdet; nem teszi lehetővé, hogy az alkalmazása válaszoljon a lekérdezésekre. Ha saját maga akar neveket feloldani, futtasson resolvert, és irányítsa annak címét az alagútba. A fix hosztnévre DoT-ot vagy DoH-t használó alkalmazások megkerülhetik a bejelentett címet, ezért a névfeloldást legjobb igyekezetként kezelje, hacsak a lekérdezés útját is el nem fogja.

Manifest, always-on és a négy lépéses teszt

A jogosultságot a manifest deklarálja: BIND_VPN_SERVICE, az android.net.VpnService intent-szűrő, és előtér-szolgáltatás, ha az alagútnak a háttérben is fenn kell maradnia. Az always-on VPN emellett tiszta onRevoke-ot igényel, mert a rendszer akkor hívja, amikor a felhasználó módosítja a beállításokat, vagy egy másik alkalmazás átveszi az irányítást.

Futtassa az ellenőrzéseket sorrendben, és álljon meg az első hibánál. Először írja ki a buildernek átadott cím-, útvonal- és DNS-listákat. Másodszor erősítse meg, hogy az establish() leírót adott vissza, és az átviteli socket védett. Harmadszor kérjen egy célt egy benne foglalt előtagon belül és egyet egy kizárt előtagon belül. Negyedszer ellenőrizze, melyik resolver válaszolt valójában, olyan hosztnevet kérdezve, amelyet csak az ön resolverje tud feloldani.

Egy befejezett kézfogás a későbbi lépések egyikét sem bizonyítja. Minden ellenőrzés egy réteget izolál, ezért a második lépés sikere semmit nem mond a negyedikről.

A VpnService.Builder-referencia felsorolja a builder teljes felületét. Minden, ami ezen túl kell, egy másik API, egy másik alkalmazás vagy a saját felhasználói térbeli verme, és ez tervezési döntés, nem split-tunneling hiba.

Kapcsolódó cikkek