Split tunneling hajoaa VpnService-sovelluksessa muutamassa tietyssä kohdassa, ja korjaus on jokaisessa erilainen. Asiakas näyttää vain yhden epäonnistuvan kohteen, joten ensimmäinen työ on selvittää, mihin rajaan törmäät: builderin saamat reitit, proxy jota et voi todentaa, resolver josta vain ilmoitit vai alustan käyttäjäkohtaisesti soveltama sovellusluettelo. Siksi pidän nelivaiheisen tarkistuksen. Se etenee alla olevassa järjestyksessä ja pysähtyy ensimmäiseen virheeseen.

Varmista, mitä builder antoi alustalle

VpnService.Builder on julistusluettelo. establish() palauttaa virtuaaliliitännälle ParcelFileDescriptorin, ja alusta lähettää kyseiseen deskriptoriin vain liikenteen, joka vastaa addAddress- ja addRoute-prefiksejä; addDnsServer kertoo asiakkaille, mitä resolveria kysyä. Kaikkien lisäämiesi prefiksien ulkopuolinen kohde ei koskaan saavuta sovellustasi, mitä liitäntä tahansa lupaa. Tämä yksi tosiasia selittää useimmat ilmoitukset rikkinäisestä split tunnelingista jo ennen koodimuutoksia.

Kirjaa lokiin builderin kokoamat osoite-, reitti- ja DNS-luettelot ja vertaa niitä epäonnistuviin kohteisiin. Puuttuva /32 hallintakoneelle on paljon yleisempi kuin rikkinäinen tunneli. Jos luettelo on oikein, jatka; jos ei, loppu tarkistuslistasta on hukattua työtä.

excludeRoute on olemassa vasta API 33:sta

Kohdeperusteinen poissulkeminen on pyyntö, joka useimmin muuttuu tukiketjuksi. builder.excludeRoute(IpPrefix) tuli API 33:ssa; sitä ennen ainoa tuettu likiarvo on lisätä reitit kaikelle paitsi poissuljetulle prefiksille, eli komplementaariset prefiksit on laskettava itse. Kutsut eivät ole peilikuvia: toinen vähentää liitännän reittijoukosta, toinen rakentaa joukon tyhjästä, ja vanhempi laite heittää tai jättää hiljaa huomiotta kutsun, jota se ei tunne. Haarauta Build.VERSION.SDK_INT:n mukaan ja testaa molemmat polut oikealla laitteistolla.

Kun lasket komplementteja, seuraa prefiksien kohdistusta. /24-poissulkeminen /16-reitin sisällä tarvitsee kattavat prefiksit, jotka todella kuvaavat jäljelle jäävän osan, ei yhtä virheellistä /8:aa. Kirjaa lopullinen luettelo ja varmista, että poissuljettu kone vielä ratkeaa tunnelin ulkopuolista polkua pitkin.

Proxyn tunnistetietoja ei voi ilmaista

setHttpProxy(ProxyInfo) ohjaa liitännän HTTP- tai SOCKS-proxyyn, ja PAC-URL voi valita niiden välillä kohdekohtaisesti. Kumpikaan, ei ProxyInfo eikä PAC-muoto, kuljeta käyttäjätunnusta ja salasanaa, joten todennusta vaativa proxy jää alustan API:n ulkopuolelle. Sovellukset, jotka sitä tarvitsevat, upottavat yleensä käyttäjätilan pinon, tun2socksin tai vastaavan moottorin ja vastaavat 407-haasteeseen itse.

Tällä valinnalla on seurauksia. Käyttäjätilan pino näkee vain liikenteen, jonka reitität siihen, joten sen on elettävä saman deskriptorin rajoissa, ja se perii saman protect()-vaatimuksen omalle uplink-socketilleen. Jätä protect() pois, niin tunneli kaappaa oman liikenteensä, mikä näkyy kättelynä, joka juuttuu ensimmäisen paketin jälkeen. Testaa proxyä vastaan, joka vaatii tunnistetietoja, koska avoin proxy menee läpi alustan polulla eikä todista mitään.

Sovellusluettelot ja DNS ovat myös julistuksia

Builderissa on sekä addAllowedApplication että addDisallowedApplication, ja ne sulkevat toisensa pois: molempien kutsuminen heittää poikkeuksen. Joka tapauksessa luettelo sovelletaan käyttäjäkohtaisesti liitäntää asetettaessa, joten työprofiilin sovellusta ohjaa työprofiilin tunneli, ei sinun. Mitä mikään API ei anna, on valta toisen sovelluksen päätökseen: et voi pakottaa pakettia tunneliisi ulkopuolelta etkä sulkea tai määrittää uudelleen jo aktiivista VPN-yhteyttä.

DNS noudattaa samaa kaavaa. addDnsServer ilmoittaa resolverin osoitteen; se ei anna sovelluksesi vastata kyselyihin. Jos haluat ratkaista nimet itse, aja resolver ja reititä sen osoite tunneliin. Sovellukset, jotka käyttävät DoT:ia tai DoH:ta kiinteään konenimeen, voivat ohittaa ilmoittamasi osoitteen, joten kohtele nimien ratkaisua parhaana yrityksenä, ellet sieppaa myös kyselypolkua.

Manifest, always-on ja nelivaiheinen testi

Kelpoisuus julistetaan manifestissa: BIND_VPN_SERVICE, android.net.VpnService-intentfilter ja foreground-palvelu, jos tunnelin on selvittävä taustalla. Always-on VPN vaatii lisäksi puhtaan onRevoken, koska järjestelmä kutsuu sitä, kun käyttäjä muuttaa asetuksia tai toinen sovellus ottaa hallinnan.

Suorita tarkistukset järjestyksessä ja pysähdy ensimmäiseen virheeseen. Ensiksi tulosta builderille annetut osoite-, reitti- ja DNS-luettelot. Toiseksi varmista, että establish() palautti deskriptorin ja että kuljetussocket on suojattu. Kolmanneksi pyydä yksi kohde sisällytetyn prefiksin sisältä ja yksi poissuljetun sisältä. Neljänneksi tarkista, mikä resolver todella vastasi, kysymällä konenimeä, jonka vain sinun resolverisi voi ratkaista.

Valmis kättely ei todista mitään myöhemmistä vaiheista. Jokainen tarkistus eristää yhden kerroksen, joten toisen vaiheen onnistuminen ei kerro neljännestä mitään.

VpnService.Builder-viite luettelee builderin koko pinnan. Kaikki sen ulkopuolella tarvittava on toinen API, toinen sovellus tai oma käyttäjätilan pinosi, ja se on suunnitteluvalinta, ei split-tunneling-vika.

Aiheeseen liittyvät artikkelit