Firwat Ären Android VpnService-Tunnel opgehéiert Verkéier ze routeren
Véier VpnService-Virstellungen, déi a Produktioun briechen: een Tunnel op eemol, Ëmfang vun de Routen, Lëschten pro App an d'Reiefolleg beim Ausschalten, mat enger Kontroll fir jidderee.
Véier Viraussetzungen iwwer Android VpnService hunn mir eng Kéier de gréissten Deel vun enger Woch kascht, an keng dovun huet sech mam Netzwierkprotokoll befaasst. D'App huet gesot verbonnen, de Schlëssel-Ikon huet an der Statusbar gesiess, an de Verkéier ass awer weider iwwer de normalen Trajet erausgaangen. Ech hu weider ugeholl, datt den Tunnel meng ass bis ech en ophalen, datt d'Routen, déi ech bäigefüügt hunn, déi Routen sinn, déi ech kréien, an datt en Opruff vun stopSelf d'Interface mat sech erofhuele géif. Den Déngscht huet sech genee esou beholl, wéi et dokumentéiert ass. De kaputten Deel war mäi mentale Modell.
Mythos 1: den Tunnel bleift uewen, bis Dir en ophaalt
Android hält ee VPN-Interface op eemol. Richt en zweeten an, an d'Plattform setzt en net an d'Schluecht: si deaktivéiert Ären an an Ärem Déngscht rifft si onRevoke() op. Wann Äre Code nëmmen op Knappdrécke leeft, léisst eng Iwwernuemung en Deskriptor an en Lies-Thread hanner sech, an de nächsten Start ierft béides.
D'VpnService-Referenz seet kloer, datt prepare() null zréckgëtt, wann d'App schonn eng Zoustëmmung huet, an en Intent, wann de Benotzer nach muss zoustëmmen. Déi Zoustëmmung kënnt nëmmen un, wann Dir den Intent iwwer startActivityForResult() liwwert. Loosst d'Iwwergab aus, an establish() gëtt null zréck, wat als stille Feeler an net als Berechtegungsproblem gelies gëtt.
Always-on VPN füügt en Eegentimer bäi, deen Dir net kontrolléiert. De System kann den Tunnel no engem Start oder no engem Crash zréckbréngen, an en dréckt eng VPN-App of, déi de Benotzer vun Hand gestart huet. Baut onRevoke() esou, datt en déi selwecht Ressourcen zoumaacht wéi Ären normale Ausschalten, an behandelt en als Haaptstoppwee an net als Randfall. Benotzer wiesselen VPN-Appen; Äre Code muss dat iwwerstoen.
Mythos 2: addRoute fänkt genee dat, wat Dir opgezielt hutt
D'Routen entscheeden, wéi eng Pakete bis bei Ären Deskriptor kommen, an en Ëmfangsfeeler produzéiert dee verréckten Fall, an deem en Deel vum Verkéier duerch den Tunnel geet an en aneren net. addRoute("0.0.0.0", 0) hëlt de ganzen IPv4, wat heescht, datt all Paket elo bei Iech ukommt an et muss virugereecht oder verworf ginn. En /32 fir een eenzegen Host hëlt bal näischt, an alles anescht behält sech, wéi wann Äre VPN ni installéiert gouf.
D'Famillje ginn getrennt gezielt. Eng Route just fir IPv4 léisst IPv6 um ënnerleeënde Netzwierk, dofir kann en Dual-Stack-Host nach ëmmer baussen dem Tunnel opléisen an sech verbannen, wärend en dobannen ganz verbonne schéngt.
DNS suivelt der selwechter Logik. Server, déi mat addDnsServer() bäigefüügt ginn, ginn un Appen, déi de Resolver vum Tunnel benotzen, wärend eng App mat engem eegene verschlësselte DNS-Endpunkt oder Private DNS, deen op en Hostnumm gesat ass, se komplett ignoréiert. Wann Nimm fir eng App feelgeschloe ginn an fir eng aner funktionéieren, kontrolléiert de Resolver-Wee, ier Dir eng eenzeg Route beréiert.
Mythos 3: App-Regele si en Schalter, deen Dir an béid Richtunge kënnt dréien
addDisallowedApplication() an addAllowedApplication() sinn zwee Modus, net zwee Filter. De Builder akzeptéiert ee Modell pro Tunnel, dofir benotzt eng App, déi alles ausser dräi Paketen wëllt, d'verbuet Lëscht an hält d'erlaabt Lëscht eidel. Déi zwee schléissen sech géigesäiteg aus, an d'Leit fannen dat zur Lafzäit eraus, nodeems den Astellungsbildschierm scho béid Schalter ugebueden huet.
D'Siichtbarkeet vun de Pakete bäisst och. Zënter Android 11 kënnt Dir nëmmen déi Pakete bezeechnen, déi Dir gesitt, dofir verléiert eng Ausnamlëscht, déi aus enger Ufro gebaut gouf, déi Är App net däerf ausféieren, stillschweigend Einträg. Vergläicht d'Lëscht mat deem wat de Paketmanager tatsächlech zréckgëtt, ier Dir hir vertraut.
Aarbechtsprofile deelen d'Publikum nach eng Kéier. En Tunnel, deen am Profil gestart gëtt, deckt dee Profil an seng Appen of, wärend déi perséinlech Säit hir eege Verbindung behält. Dat ass eng eemol getraffent Ëmfangsentscheedung, an se gehéiert an d'Interface an net an en Support-Ticket.
Mythos 4: stopSelf beend den Tunnel
Neen. D'Interface lieft am Deskriptor, deen establish() zréckgëtt, an d'Déngschtobjekt ka stierwen, wärend deen Deskriptor op bleift. Maacht fir d'éischt den ParcelFileDescriptor zou, loosst d'Referenz falen, verbënnt Iech mat de Lies- a Schreiwthreaden oder ënnerbrach se, an da rifft stopForeground(true) an stopSelf() an där Reiefolleg un.
En vergiessen Deskriptor ass de gewéinleche Grond, firwat en Déngscht seng eegene Stoppufro schéngt z'iwwerliewen, an et erkläert eng verouderte Route, déi méi laang lieft wéi d'App, déi se bäigefüügt huet.
De Géigendeel-Feeler ass genee sou heefeg: den Deskriptor zoumaachen, wärend en Lies-Thread an der Mëtt vum Liese steet, an dann deen Thread eng Ausnam behandele loossen, fir déi keen eppes geschriwwen huet. Halt d'Reiefolleg beim Ausschalten op enger Plaz, a loosst souwuel dem Benotzer seng Aktioun wéi och onRevoke() dohinner ruffen.
Wat ze kontrolléieren, wann den Tunnel dout schéngt
Schützt laangdauernd Sockets mat protect(), ier den Tunnel eropkënnt. Ouni dat gëtt den Transport vum Tunnel selwer zréck an den Tunnel geroutet, an d'Verbindung stockt op eng Manéier, déi genee wéi e Serverfeeler aussäit. Testt géint eng Adress, déi et just hannert dem feme Netzwierk gëtt, net géint eng ëffentlech Säit, déi aus dem Cache oder vum ënnerleeënde Wee äntwert.
Logt d'Resultat vun establish(), d'Routen, déi ausgeschloss Paketen an de Grond vum Ausschalten. Déi véier Zeilen trennen e Zoustëmmungsproblem vun engem Ëmfangsproblem an engem Liewenszyklusproblem ouni Paketopnam.