Split tunneling i ein VpnService-app bryt saman på nokre få konkrete stader, og reparasjonen er ulik for kvar av dei. Klienten viser berre éin destinasjon som feilar, så den første oppgåva er å finne ut kva grense du treffer: rutene builderen fekk, proxyen du ikkje kan godkjenne, resolveren du berre kunngjorde, eller app-lista plattforma brukar per brukar. Nettopp difor held eg ein kontroll i fire trinn. Han går i rekkjefølgja nedanfor og stoppar ved første feil.

Stadfest kva builderen gav plattforma

VpnService.Builder er ei liste over deklarasjonar. establish() returnerer ein ParcelFileDescriptor for eit virtuelt grensesnitt, og plattforma sender berre trafikk som svarar til prefiksa frå addAddress og addRoute, inn i den deskriptoren; addDnsServer fortel klientane kva resolver dei skal spørje. Ein destinasjon utanfor alle prefiksa du la til, når aldri appen din, kva grensesnittet enn lovar. Denne eine kjensgjerninga forklarer dei fleste rapportane om broten split tunneling før nokon kode blir endra.

Logg adresse-, rute- og DNS-listene builderen din sette saman, og samanlikn dei med destinasjonane som feilar. Eit manglande /32 for ein administrasjonsvert er langt vanlegare enn ein broten tunnel. Er lista rett, gå vidare; er ho feil, er resten av sjekklista bortkasta arbeid.

excludeRoute finst først frå API 33

Destinasjonsbasert utelukking er førespurnaden som oftast blir ein støttetråd. builder.excludeRoute(IpPrefix) kom i API 33; før det er den einaste støtta tilnærminga å leggje til ruter for alt utanom det utelukka prefikset, som tyder at du må rekne ut dei komplementære prefiksa sjølv. Dei to kalla er ikkje spegelbilete: det eine trekkjer frå rutessettet til grensesnittet, det andre byggjer settet frå botnen, og ein eldre eining vil kaste eller stille oversjå eit kall ho ikkje kjenner. Forgrein på Build.VERSION.SDK_INT, og test begge vegar på ekte maskinvare.

Når du reknar ut komplement, følg med på prefiksjusteringa. Ei /24-utelukking inne i ei /16-rute treng dei dekkjande prefiksa som faktisk skildrar resten, ikkje ein einaste feilforma /8. Logg den endelege lista, og stadfest at den utelukka verten framleis blir løyst opp via ein veg utanfor tunnelen.

Proxy-legitimasjon kan ikkje uttrykkjast

setHttpProxy(ProxyInfo) peikar grensesnittet mot ein HTTP- eller SOCKS-proxy, og ein PAC-URL kan velje mellom dei per destinasjon. Korkje ProxyInfo eller PAC-formatet ber brukarnamn og passord, så ein proxy som krev godkjenning, ligg utanfor API-et til plattforma. Appar som treng det, byggjer vanlegvis inn ein userspace-stakk, tun2socks eller ein liknande motor, og svarar sjølv på 407-utfordringa.

Det valet har konsekvensar. Ein userspace-stakk ser berre trafikk du ruter til han, så han må leve innanfor same deskriptorgrensa, og han arvar same protect()-kravet for sin eigen uplink-socket. Hopper du over protect(), fangar tunnelen sin eigen transport, noko som viser seg som eit handtrykk som stoppar etter den første pakka. Test mot ein proxy som krev legitimasjon, for ein open proxy passerer på vegen til plattforma og provar ingenting.

App-lister og DNS er òg deklarasjonar

Builder har både addAllowedApplication og addDisallowedApplication, og dei utelukkar kvarandre: å kalle begge kastar ein feil. Uansett blir lista brukt per brukar ved oppsett av grensesnittet, så ein app i arbeidsprofilen blir styrt av tunnelen til arbeidsprofilen og ikkje din. Det ingen API gir deg, er kontroll over avgjerda til ein annan app: du kan ikkje presse ei pakke inn i tunnelen din utanfrå, og du kan ikkje lukke eller omkonfigurere ein VPN som alt er aktiv.

DNS følgjer same mønster. addDnsServer kunngjer ei resolveradresse; det lèt ikkje appen din svare på spørjingar. Vil du løyse opp namn sjølv, køyr ein resolver og rut adressa hans inn i tunnelen. Appar som brukar DoT eller DoH mot eit fast vertsnamn, kan omgå adressa du kunngjorde, så handsam namneoppslag som beste innsats med mindre du òg fangar opp spørjevegen.

Manifest, always-on og firetrinnstesten

Kvalifisering blir deklarert i manifestet: BIND_VPN_SERVICE, intent-filteret android.net.VpnService og ein forgrunnsteneste om tunnelen må overleve i bakgrunnen. Always-on VPN krev i tillegg ein rein onRevoke, fordi systemet kallar han når brukaren endrar innstillingar eller ein annan app tek over kontrollen.

Køyr kontrollane i rekkjefølgje, og stopp ved første feil. Først: dump adresse-, rute- og DNS-listene som vart gjevne til builderen. Deretter: stadfest at establish() returnerte ein deskriptor, og at transportsocketen er verna. Tredje: be om éin destinasjon inne i eit inkludert prefiks og éin inne i eit utelukka prefiks. Fjerde: sjekk kva resolver som faktisk svara, ved å spørje på eit vertsnamn berre resolveren din kan løyse.

Eit fullført handtrykk provar ingen av dei seinare trinna. Kvar kontroll isolerer eitt lag, så ein passering ved trinn to seier ingenting om trinn fire.

VpnService.Builder-referansen listar heile builder-flata. Alt du treng utover det, er eit anna API, ein annan app eller din eigen userspace-stakk, og det er ei designavgjerd snarare enn ein split-tunnel-feil.

Relaterte artiklar