Android-VPN-attributie: getConnectionOwnerUid versus /proc/net
Android 10 verbergt /proc/net voor apps. Een VPN krijgt nog steeds pakketten, maar attributie verschuift naar getConnectionOwnerUid, met eigen tuple- en permissieregels.
Op Android 10 en later krijgt een app die /proc/net/tcp opent een toegangsweigering in plaats van een sockettabel. De VPN-interface kan het niet schelen: pakketten komen nog steeds binnen, want de tunnel is een routeringsbeslissing, geen bestandspermissie. Wat veranderde is het antwoord op een nauwere vraag: „welke app bezit deze verbinding?“ De vervanging is ConnectivityManager.getConnectionOwnerUid, de ondersteunde query per verbinding, en de keuze tussen de oude gewoonte en de nieuwe API hangt af van welke van drie taken je werkelijk hebt: pakketten ontvangen, een stroom attribueren of gebruik optellen.
Twee manieren om de eigenaarsvraag te beantwoorden
Vóór API 29 kon een geprivilegieerd proces of root de sockettabellen van de kernel lezen, het viertal matchen en de eigenaar-UID achterhalen. Dat gaf een apparaatbrede inventaris in één bestand. Vanaf API 29 is de bestandssysteemweergave beperkt, en de ondersteunde route is een query per verbinding met het protocol, het lokale adres en het externe adres.
| Question | Legacy socket tables | getConnectionOwnerUid |
|---|---|---|
| Who owns this flow? | Scan and match the tuple | Ask once per tuple |
| Device-wide inventory? | Yes, when readable | No, one flow at a time |
| Historical usage? | No | No; that is NetworkStatsManager |
| Works without root? | No on modern releases | Yes, for authorized callers |
De vergelijking is niet „oud versus nieuw“. Het zijn drie verschillende taken die vroeger door één leesbaar bestand werden vervuld en nu door drie verschillende interfaces met drie verschillende contracten.
Het lokale adres is het eindpunt van de app
De methodesignatuur neemt een protocol, een lokaal socketadres en een extern socketadres. „Lokaal“ betekent de kant van de app in de verbinding, niet het eindpunt dat op het moment van inspectie toevallig de bron van het pakket is. Een pakket dat van de externe server terug naar de app reist, heeft bron en bestemming omgekeerd ten opzichte van die definitie.
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);Deze richtingsfout is de meest voorkomende reden dat een werkende query het verkeerde antwoord geeft, of geen. Log beide eindpunten vóór de aanroep en bevestig het paar tegen de verbinding die de app werkelijk opende. De adresfamilie telt ook: een IPv4-gemapt adres en een native IPv6-adres zijn verschillende tuples, en dat geldt ook voor TCP- en UDP-stromen op dezelfde poorten.
Autorisatie en onbekende resultaten horen bij het contract
De query is beperkt tot geautoriseerde aanroepers, waaronder de actieve VPN-app voor de betreffende gebruiker. Een ongerelateerde monitoring-app kan niet aannemen dat hij de verbindingen van een ander profiel kan opsommen, en een niet-geautoriseerde aanroep kan een beveiligingsuitzondering gooien in plaats van een vriendelijke fout terug te geven. Behandel beide uitkomsten expliciet.
Een ontbrekende eigenaar is geen pakketnaam. De stroom kan gesloten zijn tussen het pakket en de query, de tuple kan onvolledig zijn, of de aanroeper mag het simpelweg niet weten. Het eerste geslaagde antwoord cachen en later hergebruiken schrijft een nieuwe verbinding toe aan een oude app, wat erger is dan onbekend melden.
Wanneer attributie mislukt, heeft het verkeer nog steeds een beslissing nodig: blokkeer het waar het beleid dat vereist, sta alleen een bereik toe dat je begrijpt, of maak de kloof zichtbaar. Die terugval hoort bij het ontwerp, niet bij een commentaar.
Boekhouding is een andere vraag
NetworkStatsManager rapporteert gebruik volgens zijn eigen toegangsregels. Het kan je vertellen hoeveel een UID over een periode heeft overgedragen; het kan je niet de eigenaar van een willekeurig levend pakket vertellen. Netwerkmogelijkheden beschrijven eigenschappen van een netwerk, geen map van sockets. De drie mengen levert dashboards op die consistent lijken en het niet zijn.
Voor het eenvoudige geval om te bepalen welke apps de tunnel gebruiken, drukken Androids ondersteunde lijsten van toegestane en verboden apps het beleid al uit zonder iets te scrapen. Reserveer attributie per stroom voor de gevallen die het echt nodig hebben, en begroot een onderhouden implementatie die richting, permissies en onbekende toestanden samen afhandelt.
Kies het gereedschap op taak en test dan de randen
Als de eis tunnelkeuze is, gebruik de platformlijst. Als het live-attributie is, gebruik de eigenaarquery en behandel elke onbeantwoordbare tuple als onbekend. Als het historische totalen zijn, gebruik de stats-API. Test dan de drie randen die naïeve implementaties breken: een pakket in tegengestelde richting, een stroom die sluit voordat je hem opvraagt, en een aanroeper die niet de actieve VPN is.
Niets hiervan vereist het uitschakelen van SELinux, het rooten van de telefoon of het wereldwijd leesbaar maken van kerneltabellen. De beperking is het punt: het platform verplaatste attributie achter een contract zodat het antwoord beschikbaar is voor het component dat het legitiem nodig heeft, en voor niemand anders.