Android chroot VPN: hvorfor tunnelen virker og appene ignorerer den
Chroot endrer bare banesøk, ikke kjernen, nettverksnavnerommet eller Androids VPN-registrering. Det gir to utfall, og begge overrasker folk.
Du får en Linux-distribusjon som kjører under chroot på telefonen, installerer en VPN-klient i den, og skallet melder at tunnelen er ferdig. Så bytter du til en nettleser, og trafikken går ut over mobildata som om ingenting hadde skjedd. Eller det motsatte: hver app på telefonen mister tilkoblingen fordi klienten la inn en standardrute i navnerommet Android faktisk bruker. Begge symptomene kommer fra den samme manglende brikken, og ingen av dem er en feil i VPN-klienten.
Skallet sier tilkoblet, appene er uenige
Det første utfallet er det vanlige. En brukerromstunnel åpnet fra chroot kan fullføre håndtrykket, skrive ut statistikken og frakte trafikk som det samme skallet genererer, mens Androids apper fortsetter å bruke telefonens standardnettverk. Ingenting fanger dem opp, fordi ingenting fortalte Android at en VPN finnes.
Det andre utfallet er det farlige. Hvis chroot deler Androids nettverksnavnerom, noe den gjør som standard, kan en prosess med nok privilegier legge til ruter og et TUN-grensesnitt som påvirker hele telefonen. Da virker tunnelen for hver app, også de du ikke hadde tenkt å rute, og telefonens tilkobling avhenger nå av en tjeneste uten livssyklusstyring, uten tilkoblingsindikator og uten alltid-på-policy.
Hvilket av de to du fikk, kan avgjøres med én kommando. Sammenlign ip route inne i chroot med den samme kommandoen fra et Android-skall utenfor. Identisk utdata betyr at chroot er i vertens navnerom: enhver nettverksendring den gjør, gjelder hele telefonen. Ulike utdata betyr at oppstarteren laget et navnerom for den, og tunnelen er usynlig for Android av natur.
Hva chroot endret og hva den ikke endret
| Object | Effect of a chroot |
|---|---|
| Pathname resolution | Changed: lookups start at the new root |
| Kernel and drivers | Unchanged: the phone's kernel, its TUN driver, its limits |
| Network namespace | Unchanged unless the launcher creates one |
| Android VPN registration | Unchanged: no app consented, no VPN is selected |
Systemkallet chroot gjør én ting: det endrer katalogen som brukes til å slå opp banenavn. Man-siden sier tydelig at det ikke er en sikkerhetsgrense, og den sier ingenting om grensesnitt, ruter eller VPN-tilstand. Alt folk forventer av en Linux-container — en privat nettverksstakk, et filtrert filsystem, ressursgrenser — kommer fra andre mekanismer som oppstarteren kan ha brukt eller ikke.
Derfor svarer påstander om at chroot isolerer en VPN vanligvis på feil spørsmål. Det relevante spørsmålet er hvilket navnerom prosessen kjører i og hvilket SELinux-domene den er begrenset til, og begge er egenskaper ved hvordan den ble startet, ikke ved ordet chroot.
TUN trenger tre ting, og en enhetsnode er bare én
En tradisjonell brukerromstunnel trenger en TUN-enhet den kan åpne, kjernestøtte for den enheten og tillatelse til å konfigurere grensesnittet og rutene. Dette er separate krav, og å lage et banenavn under /dev oppfyller ingen av dem i seg selv:
ls -l /dev/net/tun
ip tuntap add dev tun0 mode tun
På Android har kjernen vanligvis TUN-støtte kompilert inn, fordi plattformens egen VPN-tjeneste bruker det, men det betyr ikke at prosessen din får bruke det. Grensesnittkonfigurasjon krever nettverksadministrasjonsrettigheter, og SELinux avgjør om prosessen i det hele tatt får nå enhetsnoden. En avvisning ser ut som en tilgangsfeil uten åpenbar årsak, og svaret finnes i revisjonsloggen:
dmesg | grep avc
logcat -d | grep "avc: denied"
Root løser ikke dette. SELinux begrenser prosesser som kjører som uid 0 akkurat som andre, så en chroot startet fra et root-skall kan fortsatt bli nektet en enhet den ser. Å slå av håndhevelsen for å få en gammel installasjonspakke til å virke er en beslutning for hele telefonen med konsekvenser langt utover tunnelen, og det er ingen retting av en utdatert binærfil.
Hvorfor Android-apper ignorerer tunnelen din
Androids støttede modell er en VPN-app som registrerer seg gjennom plattformens VPN-tjeneste, ber brukeren om samtykke én gang og mottar en fildeskriptor for tunnelen. Plattformen ruter deretter trafikken inn i den deskriptoren og håndhever appomfanget brukeren eller administratoren valgte, og derfor kan den samme mekanismen være per app, per profil og kombinert med alltid-på og blokker-uten-VPN-innstillinger. Androids VPN-utviklingsveiledning beskriver det håndtrykket, og poenget er at det er en registrering, ikke et rutetriks.
En tjeneste inne i chroot registrerer seg aldri. Det finnes ingen samtykkedialog, ingen nøkkelikon i statuslinjen, ingen liste for å inkludere eller utelate apper, og ingen deltakelse i alltid-på-policyen. Appene fortsetter derfor å bruke standardnettverket, og tunnelen frakter bare det skallet selv sender.
Den andre veien hjelper heller ikke. Å dytte ruter inn i vertens navnerom fanger alt, også trafikk plattformen forventet å holde lokalt, og det skjer uten kontroll per app og uten at brukeren kan se eller trekke det tilbake. Det finnes ingen mellominnstilling der en chroot-tjeneste ruter trafikk for bare én app.
Binærkompatibilitet er en egen mur
Selv når nettverkssiden er interessant, har den kjørbare filen sine egne krav: CPU-arkitektur, den dynamiske lasteren, C-biblioteket og kjernelavnene den forventer. Android bruker bionic i stedet for glibc, og en gammel binærfil bygget for en skrivebordsdistribusjon kan trenge biblioteker som ikke lenger finnes på enheten.
Å lenke et bibliotekfilnavn symbolsk til en nyere versjon gir ikke ABI-kompatibilitet, og et arkivert kryptobibliotek fra en ti år gammel pakke er ikke en vedlikeholdt komponent. Hvis planen avhenger av det, er planen å kjøre uvedlikeholdt kode med nettverksprivilegier på en telefon.
Bevis det i Android-konteksten og rydd opp etterpå
Test det du faktisk bryr deg om, fra den siden som betyr noe: åpne den bestemte appen, nå den bestemte private destinasjonen, bekreft hvilken resolver som svarte, koble deretter fra tunnelen og bekreft den dokumenterte oppførselen. Et resultat fra en terminal inne i chroot er bevis om den terminalens kjørekontekst og ingenting mer.
Hvis du endret vertsruter mens du eksperimenterte, sett dem tilbake og skriv ned hva du endret. Sjekk deretter om telefonen har en alltid-på-VPN konfigurert, fordi et eldre eksperiment som la igjen en regel kan se ut som en plattformfeil måneder senere.
For et reelt behov for fjernaksess, bruk tjenestens støttede klient eller en godkjent gateway-utforming. Spørsmålet som er verdt å stille er ikke om en rootet installasjonspakke kan fås til å kjøre, men om en støttet implementering frakter appene du trenger over grensen du mente, uten å legge igjen eierløse privilegerte endringer på enheten.