Android VPN-ruting: policyregler før tabellen main
Android velger en rutetabell med uid- og merkeregler før noe målsoppslag, så en rute som legges til i main blir kanskje aldri spurt.
En rute som legges til tabellen main på Android ser riktig ut i enhver oversikt og frakter likevel ikke trafikken. Årsaken er at tabellen main er ett alternativ blant flere, og den spørres ikke først. Nettverkstjenesten i Android bygger policyregler som velger en rutetabell ut fra informasjon som måladdressen ikke inneholder — applikasjonens uid, et merke på pakken, grensesnittet den kom inn på — og oppslaget mot målet skjer etterpå, inne i den tabellen som disse reglene valgte.
Tre beslutninger i fast rekkefølge
En pakke på vei ut tar tre separate beslutninger. Først avgjør en policyregel hvilken rutetabell som gjelder. Deretter avgjør en rute i den tabellen neste hopp og det utgående grensesnittet. Til slutt avgjør netfilter-kroker om pakken overlever, endres eller omdirigeres.
Rekkefølgen betyr noe fordi hvert trinn bare kan svare på sitt eget spørsmål. En brannmurregel som godtar en pakke velger ikke en tabell, og en rute som legges til en tabell ingen regel velger, er inaktiv. Mye av forvirringen rundt Android-VPN-er kommer av å rette én av de tre og ikke se noen endring, fordi feilen lå i en annen.
| 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 |
Merker er et pakket felt, ikke en etikett du eier
Android pakker flere fakta inn i samme merkeverdi: hvilket nettverk som ble valgt, om en applikasjon uttrykkelig valgte et nettverk, om en socket er beskyttet mot VPN, og biter knyttet til tillatelser. AOSP sin fwmark-header definerer dette oppsettet for det gjeldende treet, og oppsettet er en plattformintern detalj som endres mellom utgivelser.
Derfor er det farlig på Android å skrive en hel merkeverdi med iptables -j MARK --set-mark. Det legger ikke til en tag; det erstatter nettverksvalget systemet allerede har gjort. Pakken samsvarer da med andre regler, noe som kan se ut som VPN-en begynte å virke, eller som at en urelatert app mistet tilkoblingen, avhengig av hvilke biter som ble overskrevet.
Hvis du må røre merker, les den gjeldende verdien først og bruk en maske slik at bare bitene du forstår endres:
ip rule show
ip route show table all | head -40
ip route get 10.20.4.11Et tilkoblingsmerke er et eget objekt fra et pakkemerke, og ingen av dem er en rute. Å gjenopprette merket på svarpakker er et annet trinn enn å velge tabell på vei ut, og derfor gir enveisrettinger tilkoblinger som åpnes og deretter henger.
Hvem eier reglene og tabellene
Nettverkstjenesten i Android, netd, lager reglene og tabellene per nettverk. AOSP RouteController er stedet der disse reglene settes sammen for VPN-er, fysiske nettverk og uid-områder, og livssyklusen er knyttet til nettverkshendelser i stedet for en konfigurasjonsfil.
To konsekvenser følger. For det første er prioriteter og tabellnumre du finner på én håndsett byggeinterne detaljer, ikke et grensesnitt: like utseende numre på en annen Android-versjon kan bety noe helt annet. For det andre bygges tilstanden på nytt når nettverk endres, så en regel som settes inn i dag fra et root-skall kan være borte etter neste Wi-Fi-overgang.
Den forsvinningen rapporteres ofte som at systemet ignorerer en rute. Det som faktisk skjedde, er at regelen som valgte tabellen ikke lenger finnes, og ruten i tabellen nå er uoppnåelig fra pakkens synspunkt. Kontroller regellisten, ikke rutelisten, når en fungerende konfigurasjon slutter å virke etter en gjentilkobling.
Spørsmål om krok-rekkefølgen har ikke noe universelt svar
Spørsmålet om iptables kjører før VPN-ruting kan ikke besvares uten å navngi pakkens vei. En lokalt generert pakke går gjennom output-kroken, der en merkeendring utløser en ny rutekontroll — et andre oppslag, ikke en etterfølgende redigering av det første. En pakke som kommer fra en tether-klient, går gjennom prerouting-veien og videresendes i stedet, og kjedene som ser den er andre.
Dermed kan samme regel være effektiv for en apps trafikk og usynlig for tether-trafikk, og en teller som blir stående på null forteller deg hvilken vei pakken tok, ikke om regelen er feil. Bruk tellere for å fastslå veien før du endrer en matchbetingelse.
Dette er også trinnet der en policyrutingsfeil blir vanskelig å se. Ruting til en tabell som finnes, men ikke inneholder målet, gir et nettverk uoppnåelig som ser ut som en brannmurslepp, mens en brannmurslepp gir en tidsavbrudd som ser ut som et rutingssvart hull.
Diagnostiser inne i systemet, eller la det være
For en autorisert gjennomgang, fastslå fire fakta før du rører noe: appens uid og profil, nettverket Android valgte for den, om VPN-en i det hele tatt inkluderer den appen, og om problemet finnes for begge adressefamilier. En utelukkelse per app forklarer svært mange rapporter om at VPN ikke virker uten noen rutingsfeil.
Les deretter reglene, maskene og tabellene som faktisk gjelder, og hold et nettverksbytte innenfor observasjonsvinduet. Hvis oppførselen endrer seg gjennom en gjentilkobling, ser du på en styrt livssyklus, ikke en manglende rute.
For vanlige krav, bruk de støttede kontrollene: inkludering og utelukkelse per app i VPN-applikasjonen, og plattformens eget nettverksvalg for alt som trenger en bestemt vei. Hvis en privilegert integrasjon virkelig må samarbeide med rutingsmaskineriet, rett deg mot implementasjonen av den nøyaktige Android-versjonen du støtter, og vedlikehold livssyklusen gjennom komponenten som eier den. Å tømme plattformkjeder eller sette inn en regel med høy prioritet gjør en diagnose om til en ekstra nettverksbehandler, og telefonen vil oppføre seg deretter.