Android VPN-routering: beleidsregels vóór de tabel main
Android kiest een routetabel met uid- en markeringsregels vóór elke bestemmingsopzoeking, dus een route die aan main wordt toegevoegd, wordt misschien nooit geraadpleegd.
Een route die op Android aan de tabel main wordt toegevoegd, ziet er in elke lijst correct uit en draagt het verkeer toch niet. De reden is dat de tabel main één optie uit meerdere is, en er wordt niet eerst naar gekeken. De netwerkdienst van Android bouwt beleidsregels die een routetabel kiezen op basis van informatie die het bestemmingsadres niet bevat — de uid van de applicatie, een markering op het pakket, de interface waarop het aankwam — en de bestemmingsopzoeking gebeurt daarna, binnen de tabel die die regels hebben gekozen.
Drie beslissingen in vaste volgorde
Een uitgaand pakket neemt drie afzonderlijke beslissingen. Ten eerste bepaalt een beleidsregel welke routetabel geldt. Ten tweede bepaalt een route in die tabel de volgende hop en de uitgaande interface. Ten derde bepalen netfilter-hooks of het pakket overleeft, wordt gewijzigd of wordt omgeleid.
De volgorde is belangrijk omdat elke fase alleen zijn eigen vraag kan beantwoorden. Een firewallregel die een pakket accepteert, kiest geen tabel, en een route die aan een tabel wordt toegevoegd die geen enkele regel kiest, is inert. Veel van de verwarring rond Android-VPN's komt voort uit het repareren van een van de drie en het niet zien van enige verandering, omdat de fout in een andere zat.
| Stage | Selector | What it cannot decide |
|---|---|---|
| Policy rule | uid range, mark, incoming interface | Which route exists inside the table |
| Route lookup | Destination prefix, longest match | Whether the packet is allowed out |
| Netfilter hook | Chain position, match conditions | Which table was selected |
Markeringen zijn een verpakt veld, geen etiket dat je bezit
Android verpakt meerdere feiten in dezelfde markeringswaarde: welk netwerk is gekozen, of een applicatie expliciet een netwerk koos, of een socket tegen de VPN is beschermd, en bits die met machtigingen te maken hebben. De fwmark-header van AOSP definieert die indeling voor de huidige tree, en de indeling is een platformintern detail dat tussen releases verandert.
Daarom is het op Android gevaarlijk om een hele markeringswaarde te schrijven met iptables -j MARK --set-mark. Het voegt geen tag toe; het vervangt de netwerkselectie die het systeem al had gedaan. Het pakket komt daarna overeen met andere regels, wat kan lijken alsof de VPN begon te werken, of alsof een niet-gerelateerde app de verbinding verloor, afhankelijk van welke bits zijn overschreven.
Als je markeringen moet aanraken, lees dan eerst de huidige waarde en gebruik een masker zodat alleen de bits die je begrijpt worden gewijzigd:
ip rule show
ip route show table all | head -40
ip route get 10.20.4.11Een verbindingsmarkering is een apart object van een pakketmarkering, en geen van beide is een route. Het herstellen van de markering op antwoordpakketten is een andere stap dan het kiezen van een tabel bij het uitgaan, en daarom leveren eenrichtingsoplossingen verbindingen op die opengaan en daarna hangen.
Wie bezit de regels en tabellen
De netwerkdienst van Android, netd, maakt de regels en de tabellen per netwerk. De AOSP RouteController is de plek waar die regels worden samengesteld voor VPN's, fysieke netwerken en uid-bereiken, en de levenscyclus is gekoppeld aan netwerkgebeurtenissen in plaats van aan een configuratiebestand.
Twee gevolgen volgen. Ten eerste zijn prioriteiten en tabelnummers die je op één toestel vindt buildinterne details, geen interface: nummers die er op een andere Android-versie hetzelfde uitzien, kunnen iets heel anders betekenen. Ten tweede wordt de toestand opnieuw opgebouwd wanneer netwerken veranderen, dus een regel die vandaag vanuit een root-shell is ingevoegd, kan na de volgende Wi-Fi-overgang verdwenen zijn.
Dat verdwijnen wordt vaak gerapporteerd als een systeem dat een route negeert. Wat er werkelijk gebeurde, is dat de regel die de tabel koos niet meer bestaat, en de route in de tabel is nu onbereikbaar vanuit het perspectief van het pakket. Controleer de regellijst, niet de routelijst, wanneer een werkende configuratie na een herverbinding stopt met werken.
Vragen over de volgorde van de hooks hebben geen algemeen antwoord
De vraag of iptables vóór het VPN-routing draait, is niet te beantwoorden zonder het pad van het pakket te benoemen. Een lokaal gegenereerd pakket gaat door de output-hook, waar een markeringswijziging een herrouteringscontrole uitlokt — een tweede opzoeking, geen retroactieve bewerking van de eerste. Een pakket dat van een tether-client komt, gaat via het prerouting-pad en wordt in plaats daarvan doorgestuurd, en de ketens die het zien zijn andere.
Dezelfde regel kan dus effectief zijn voor het verkeer van een app en onzichtbaar voor tether-verkeer, en een teller die op nul blijft, vertelt je welk pad het pakket nam, niet of de regel fout is. Gebruik tellers om het pad vast te stellen voordat je een matchvoorwaarde wijzigt.
Dit is ook de fase waarin een beleidsrouteringsfout moeilijk zichtbaar wordt. Routeren naar een tabel die bestaat maar de bestemming niet bevat, levert een netwerk onbereikbaar op dat op een firewalldrop lijkt, terwijl een firewalldrop een time-out oplevert die op een routeringszwart gat lijkt.
Diagnosticeer binnen het systeem, of laat het met rust
Voor een geautoriseerde beoordeling stel je vier feiten vast voordat je iets aanraakt: de uid en het profiel van de app, het netwerk dat Android ervoor koos, of de VPN die app ueberhaupt omvat, en of het probleem voor beide adresfamilies bestaat. Een uitsluiting per app verklaart heel veel meldingen dat de VPN niet werkt zonder enige routeringsfout.
Lees daarna de regels, maskers en tabellen die werkelijk van kracht zijn, en houd een netwerkwissel binnen het observatievenster. Als het gedrag verandert over een herverbinding, kijk je naar een beheerde levenscyclus, niet naar een ontbrekende route.
Voor gewone vereisten gebruik je de ondersteunde bediening: insluiting en uitsluiting per app in de VPN-applicatie, en de eigen netwerkselectie van het platform voor alles wat een specifiek pad nodig heeft. Als een geprivilegieerde integratie echt moet samenwerken met de routeringsmachinerie, richt je dan op de implementatie van de exacte Android-versie die je ondersteunt en onderhoud de levenscyclus via het component dat er eigenaar van is. Platformketens flushen of een regel met hoge prioriteit invoegen maakt van een diagnose een tweede netwerkbeheerder, en de telefoon zal zich dienovereenkomstig gedragen.