Fra Android 10 og oppover får en app som åpner /proc/net/tcp avvist tilgang istedenfor en socket-tabell. VPN-grensesnittet merker ingenting til det: pakkene ankommer fortsatt, fordi tunnelen er et rutevalg og ikke en filrettighet. Det som er nytt, er svaret på et mer avgrenset spørsmål: «hvilken app eier denne forbindelsen?» Det nye svaret er ConnectivityManager.getConnectionOwnerUid, det støttede oppslaget per forbindelse, og hvilket av de tre behovene du egentlig har – motta pakker, attribuere en strøm eller summere forbruk – avgjør om du bør bruke den gamle vanen eller det nye API-et.

To måter å besvare spørsmålet om eier

Fram til API 29 kunne en privilegert prosess eller root lese kjernens socket-tabeller, sammenligne firedobbelen og finne eier-UID-en. Det ga en oversikt for hele enheten i én fil. Etter API 29 er filsystemet begrenset, og den støttede metoden er et oppslag per forbindelse basert på protokoll, lokal adresse og ekstern adresse.

QuestionLegacy socket tablesgetConnectionOwnerUid
Who owns this flow?Scan and match the tupleAsk once per tuple
Device-wide inventory?Yes, when readableNo, one flow at a time
Historical usage?NoNo; that is NetworkStatsManager
Works without root?No on modern releasesYes, for authorized callers

Dette er ikke «gammelt mot nytt». Det handler om tre ulike behov som tidligere ble dekket av én lesbar fil, og som nå dekkes av tre ulike grensesnitt med hver sin kontrakt.

Den lokale adressen er appens endepunkt

Signaturen tar en protokoll, en lokal socket-adresse og en ekstern socket-adresse. «Lokal» viser til appens side av forbindelsen, ikke den enden som tilfeldigvis er pakkens opphav når du undersøker den. En pakke som kommer fra tjenersiden og tilbake til appen, har opphav og mål snudd i forhold til denne definisjonen.

ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
    OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);

Denne retningsfeilen er den vanligste grunnen til at et oppslag som burde virke, gir feil svar eller ingenting. Skriv begge endepunktene til loggen før kallet, og kontroller paret mot forbindelsen appen faktisk åpnet. Adressefamilien har også betydning: en IPv4-mappet adresse og en naturlig IPv6-adresse er forskjellige tupler, og det samme gjelder TCP- og UDP-strømmer på de samme portene.

Autorisasjon og ukjente resultater er en del av kontrakten

Oppslaget er forbeholdt autoriserte kallere, inkludert den aktive VPN-appen til den aktuelle brukeren. En urelatert overvåkingsapp kan ikke regne med å kunne liste opp forbindelsene til en annen profil, og et kall uten autorisasjon kan utløse et sikkerhetsunntak istedenfor å gi en hyggelig feilmelding. Begge utfallene må håndteres eksplisitt.

Manglende eier er ikke det samme som et pakkenavn. Strømmen kan ha blitt lukket mellom pakken og oppslaget, tuple-en kan være ufullstendig, eller kalleren kan rett og slett ikke ha lov til å vite det. Å lagre det første vellykkede svaret og gjenbruke det senere gir en ny forbindelse en gammel app som eier, og det er verre enn å si at svaret er ukjent.

Når attribusjonen svikter, må trafikken likevel håndteres: blokker der policyen krever det, tillat bare et omfang du forstår, eller gjør hullet synlig. Denne reserveløsningen hører hjemme i designet, ikke i en kommentar.

Regnskap er et annet spørsmål

NetworkStatsManager rapporterer forbruk etter egne tilgangsregler. Den kan si hvor mye en UID overførte i en periode, men ikke hvem som eier en vilkårlig pakke som er i live. Nettverksfunksjoner beskriver et nettverks egenskaper, ikke en oversikt over sockets. Blandes de tre, får man dashbord som ser riktige ut uten å være det.

For det enkle tilfellet der man skal avgjøre hvilke apper som bruker tunnelen, sier Androids støttede lister over tillatte og forbudte apper allerede hva policyen er, uten å hente ut noe. Bruk attribusjon per strøm bare der det virkelig trengs, og sett av ressurser til en vedlikeholdt løsning som håndterer retning, tillatelser og ukjente tilstander samlet.

Velg verktøy ut fra oppgaven, og test så kantene

Er kravet valg av tunnel, bruk plattformens liste. Er det attribusjon i sanntid, bruk eieroppslaget og behandle hver tuple som ikke kan besvares, som ukjent. Er det historiske totaler, bruk stats-API-et. Deretter bør de tre kanttilfellene testes, for det er de som knekker enkle implementasjoner: en pakke i motsatt retning, en strøm som lukkes før oppslaget, og en kaller som ikke er den aktive VPN-en.

Ingen av delene krever at SELinux slås av, at telefonen rootes eller at kjernetabellene gjøres lesbare for alle. Begrensningen er hele poenget: plattformen har flyttet attribusjonen bak en kontrakt, slik at svaret er tilgjengelig for den komponenten som har et legitimt behov for det, og for ingen andre.

Relaterte artikler