Android-VPN-toerekening: getConnectionOwnerUid teenoor /proc/net
Android 10 verberg /proc/net vir program. 'n VPN kry steeds pakkette, maar toerekening skuif na getConnectionOwnerUid, met sy eie tuple- en toestemmingsreëls.
Op Android 10 en later kry 'n program wat /proc/net/tcp oopmaak 'n toegangsweiering in plaas van 'n soktabel. Die VPN-koppelvlak steur hom nie daaraan nie: pakkette kom steeds in, want die tonnel is 'n roetebeslissing, nie 'n lêertoestemming nie. Wat verander het, is die antwoord op 'n nouer vraag: “watter toepassing besit hierdie verbinding?” Die plaasvervanger is ConnectivityManager.getConnectionOwnerUid, die ondersteunde navraag per verbinding, en die keuse tussen die ou gewoonte en die nuwe API hang daarvan af watter een van drie take jy werklik het: pakkette ontvang, 'n vloei toereken of verbruik optel.
Twee maniere om die eienaarvraag te beantwoord
Voor API 29 kon 'n bevoorregte of root-proses die kernel se soktabelle lees, die vier-tuple pasmaak en die eienaar-UID leer ken. Dit het 'n toestelwye inventaris in een lêer gegee. Vanaf API 29 is die lêerstelsel-aansig beperk, en die ondersteunde roete is 'n navraag per verbinding met die protokol, die plaaslike adres en die afgeleë 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 |
Die vergelyking is nie “oud teenoor nuut” nie. Dit is drie verskillende take wat vroeer deur een leesbare lêer bevredig is en nou deur drie verskillende koppelvlakke met drie verskillende kontrakte bevredig word.
Die plaaslike adres is die program se eindpunt
Die metodehandtekening neem 'n protokol, 'n plaaslike sokadres en 'n afgeleë sokadres. Plaaslik beteken die toepassing se kant van die verbinding, nie watter eindpunt ook al die pakket se bron is op die oomblik dat jy dit ondersoek nie. 'n Pakket wat van die afgeleë bediener terug na die program reis, het sy bron en bestemming omgekeer relatief tot daardie definisie.
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);Hierdie rigtingfout is die mees algemene rede waarom 'n werkende navraag die verkeerde antwoord gee, of geen. Teken albei eindpunte aan voor die oproep en bevestig die paar teen die verbinding wat die program werklik geopen het. Adresfamilie maak ook saak: 'n IPv4-omgeskakelde adres en 'n native IPv6-adres is verskillende tuples, en so ook TCP- en UDP-vloei op dieselfde poorte.
Magtiging en onbekende resultate is deel van die kontrak
Die navraag is beperk tot gemagtigde oproepers, insluitend die aktiewe VPN-toepassing vir die betrokke gebruiker. 'n Onverwante moniteringsprogram kan nie aanneem dat hy 'n ander profiel se verbindings kan opsom nie, en 'n ongemagtigde oproep kan 'n sekuriteitsuitsondering gooi eerder as om 'n vriendelike fout terug te gee. Hanteer albei uitkomste eksplisiet.
'n Ontbrekende eienaar is nie 'n pakketnaam nie. Die vloei kon tussen die pakket en die navraag gesluit het, die tuple kon onvolledig wees, of die oproeper mag eenvoudig nie weet nie. Om die eerste suksesvolle antwoord te kas en later te hergebruik, ken 'n nuwe verbinding aan 'n ou program toe, wat erger is as om onbekend te rapporteer.
Wanneer toerekening misluk, het die verkeer steeds 'n besluit nodig: blokkeer dit waar die beleid dit vereis, laat slegs 'n omvang toe wat jy verstaan, of wys die gaping. Daardie terugval hoort in die ontwerp, nie in 'n kommentaar nie.
Rekeningkunde is 'n ander vraag
NetworkStatsManager rapporteer verbruik onder sy eie toegangsreels. Dit kan jou sê hoeveel 'n UID oor 'n tydperk oorgedra het; dit kan nie die eienaar van 'n willekeurige lewendige pakket se nie. Netwerkvermoeens beskryf 'n netwerk se eienskappe, nie 'n gids van sokkette nie. Om die drie te meng lewer paneelborde wat konsekwent lyk en nie is nie.
Vir die eenvoudige geval om te besluit watter programme die tonnel gebruik, druk Android se ondersteunde lyste van toegelate en verbode toepassings die beleid al uit sonder om iets te skraap. Hou toerekening per vloei vir die gevalle wat dit werklik nodig het, en begroot vir 'n onderhoude implementering wat rigting, toestemmings en onbekende toestande saam hanteer.
Kies die gereedskap volgens taak, toets dan die rande
As die vereiste tonnelkeuse is, gebruik die platformlys. As dit lewendige toerekening is, gebruik die eienaar-navraag en behandel elke onbeantwoordbare tuple as onbekend. As dit historiese totale is, gebruik die stats-API. Toets dan die drie rande wat naive implementerings breek: 'n pakket in die teenoorgestelde rigting, 'n vloei wat sluit voordat jy dit navraag, en 'n oproeper wat nie die aktiewe VPN is nie.
Niks hiervan vereis dat jy SELinux deaktiveer, die telefoon root of kerntabelle wêreldwyd leesbaar maak nie. Die beperking is die punt: die platform het toerekening agter 'n kontrak geskuif sodat die antwoord beskikbaar is vir die komponent wat dit wettig nodig het, en vir niemand anders nie.