Prečo Android VpnService zachytí len časť prevádzky, a nie všetku
Trasy, záznamy DNS a rozsah podľa aplikácií rozhodujú, ktoré pakety dorazia k zariadeniu tun, prečo miestne zariadenia miznú a čo tvorca odmieta.
Nič vo VpnService samo nezachytáva prevádzku. Požiada systém o rozhranie tun, odovzdá mu sadu adries a trás a od tej chvíle jadro kopíruje každý paket zodpovedajúci týmto trasám do deskriptora súboru, ktorý aplikácia môže čítať. Kód aplikácie nikdy nevidí pakety, ktoré trasy nevybrali, takže rozsah tunela je otázka smerovacej tabuľky skôr, než sa stane otázkou programovania. Preto môže tá istá implementácia služby zhltnúť celý tok na jednom telefóne a len časť na inom, a preto pridanie trasy niekedy opraví tunel, ktorý vyzeral pokazený. Dostanete presne to, čo ste deklarovali, mínus všetko, čo tvorca ticho odmietol.
Trasy rozhodujú, ktoré pakety dorazia
Builder.addRoute(prefix, prefixLength) nainštaluje prefix do smerovacej tabuľky siete VPN. Systém považuje túto sieť za predvolenú pre aplikácie v rozsahu, takže jej záznamy sa prezerajú pred predvolenou trasou fyzickej siete a zodpovedajúci prefix stačí na odklonenie toku. Preto trasa pre 0.0.0.0/0 preberá IPv4 celý, vrátane tlačiarne, cieľa cast a administračnej stránky routera.
Klienti, ktorí chcú toto pokrytie bez vymazania fyzického predvoleného záznamu, používajú namiesto toho dvojicu 0.0.0.0/1 a 128.0.0.0/1. Dve konkrétnejšie trasy prekonajú predvolenú trasu, spolu pokrývajú celý adresný priestor a vlastný predvolený záznam telefónu zostáva v tabuľke pre sokety, ktoré sú stále viazané na fyzickú sieť.
Adresy a záznamy DNS pochádzajú od toho istého tvorcu a odpovedajú na inú otázku. addAddress dá rozhraniu adresu s dĺžkou prefixu a addDnsServer nainštaluje prekladač, ktorý budú aplikácie v rozsahu dopytovať cez rozhranie. Obe rodiny môžu sedieť na jednom rozhraní, takže sada trás len pre IPv4 vedľa adresy IPv6 je konfigurácia, ktorá sa číta správne a napriek tomu uniká. Ak smerujete rodinu, v ktorej rozhranie nemá adresu, jadro nemá zdrojovú adresu pre tieto pakety a nikdy sa neobjavia pri deskriptore.
Čo vracia establish()
establish() vracia ParcelFileDescriptor, alebo null, keď aplikácia nie je autorizovaná. Null je stav súhlasu, nie sieťová chyba: VpnService.prepare() už musel vrátiť null, alebo používateľ musel pred volaním schváliť systémový dialóg. Súhlas možno odvolať počas behu služby a rozhranie sa pod vami zavrie bez akéhokoľvek spätného volania do vašej čítacej slučky.
Deskriptor nie je blokujúci, ak neustanovíte inak, takže čítanie sa vráti okamžite bez dát, namiesto toho aby vlákno zaparkovalo. Slučka napísaná pre blokujúci soket spáli jedno jadro a slučka, ktorá prázdne čítanie považuje za fatálne, roztrhne tunel počas nečinnej sekundy. Builder.setBlocking(true) mení toto správanie a cenou je vlákno, ktoré čaká vnútri čítania.
Argumenty trasy a adresy sa overujú ako hodnoty LinkAddress a multicastové ciele ako 224.0.0.0/4 sa odmietajú rovno. Rozhranie tun bod-bod tiež nemá broadcastovú doménu, takže objavovanie multicastu cez neho potrebuje iný návrh, nie ďalšiu trasu. Referenčná príručka VpnService.Builder je zoznam, ktorý treba skontrolovať, kým usúdite, že volanie bolo ignorované.
Rozsah podľa aplikácií zužuje sadu, nie tunel
Od API 21 tvorca prijíma addAllowedApplication a addDisallowedApplication a oba zoznamy sa v jednom tvorcovi navzájom vylučujú. Zoznam povolených vytvorí tunel pre tieto pakety, zatiaľ čo všetko ostatné si ponechá fyzickú sieť; zoznam zakázaných zachytí všetko okrem uvedených paketov, čo klient ponúka ako rozdelené tunelovanie. Pred API 21 neexistuje žiadny platformový mechanizmus a správanie podľa aplikácií pochádzalo od klientov tretích strán, ktorí filtrovali podľa UID vo svojom vlastnom preposielači. Rozdiel je dôležitý pri ladení, pretože tunel podľa aplikácií so zoznamom povolených z jedného paketu takmer neprodukuje prevádzku a to je správne správanie, nie pokazená trasa.
Nech je rozsah akýkoľvek, soket, ktorý vaša aplikácia otvára k serveru VPN, nesmie cestovať tunelom, ktorý stavia. VpnService.protect(socket) pripúta tento soket k podkladovej sieti, aby jeho pakety obchádzali zariadenie tun. Ak volanie vynecháte, podanie ruky pohltí rozhranie, ktoré ho malo zdvihnúť.
VpnService.setUnderlyingNetworks uzatvára slučku tým, že systému povie, ktorá fyzická sieť nesie tunel. Táto hodnota určuje, ako VPN hlási pripojenie ostatným aplikáciám, a null alebo zastaraná hodnota je bežnou príčinou pripojeného tunela, ktorý zvyšok telefónu považuje za offline. Aktualizujte ju pri zmene podkladovej siete, nie iba pri štarte.
Kontrolné súčty a MTU: kde správna trasa napriek tomu zlyhá
Keď pakety prídu, dve podrobnosti na úrovni paketu rozhodujú, či niečo funguje od konca do konca. Prvá je zdrojová adresa: pri viacerých adresách rozhrania môže jadro vysielať pakety nesúce prvú, takže preposielač, ktorý prepisuje hlavičky, musí opraviť adresu a kontrolný súčet, ktorý ju pokrýva.
Druhá je rozsah kontrolného súčtu. Keď aplikácia stavia pakety TCP alebo UDP sama, kontrolný súčet pokrýva pseudo-hlavičku so zdrojovou adresou, cieľovou adresou, číslom protokolu a dĺžkou transportu, a vynechanie ktorejkoľvek z nich dá pakety, ktoré dorazia a zahodia sa. Táto porucha vyzerá ako časový limit po odpovedi, ktorá nikdy nepríde, čo väčšinu ľudí pošle späť k trasám. setMtu fixuje MTU rozhrania a každé čítanie vracia presne jeden úplný paket IP, takže buffer napísaný pre bajtový tok fragmentuje vaše parsovanie, nie paket.
Overovací prechod, ktorý oddeľuje vrstvy
Aby ste našli, kde sa rozsah pokazil, testujte vrstvy po poradí. Spýtajte sa zariadenia, ktoré trasy sieť VPN skutočne drží, potom skontrolujte, či sa tok na známu adresu objaví ako čítanie pri deskriptore, potom skontrolujte, či je paket, ktorý váš preposielač vysiela, správne utvorený. Problém trasy neukáže pri deskriptore nič, zatiaľ čo problém kontrolného súčtu ukáže paket, ktorý dorazí a zmizne.
Ak sa k deskriptoru nič nedostane, podozrivá je sada trás, nie čítač: overte prefixy, overte, že existuje adresa v tej istej rodine, a overte, že aplikácia je v rozsahu, ktorý ste nastavili. Ak pakety dorazia k deskriptoru, ale nič sa nevracia, pozrite sa na protect() a hodnotu podkladovej siete, kým znova siahnete na trasu. Ak vzdialená strana hlási poškodené pakety, kontrolný súčet a MTU sú miesta, kam sa pozerať. Jedna sonda na vrstvu ušetrí popoludnie hádania.