Android VPN atribucija: getConnectionOwnerUid nasuprot /proc/net
Android 10 skriva /proc/net od aplikacija. VPN i dalje prima pakete, ali atribucija prelazi na getConnectionOwnerUid, s vlastitim pravilima za tuple i dozvole.
Na Androidu 10 i novijima aplikacija koja otvori /proc/net/tcp dobiva odbijen pristup umjesto tablice socketa. VPN sučelje to ne zanima: paketi i dalje stižu, jer je tunel odluka o usmjeravanju, a ne dozvola za datoteku. Promijenio se odgovor na uže pitanje: „koja aplikacija posjeduje ovu vezu?“ Zamjena je ConnectivityManager.getConnectionOwnerUid, podržani upit po vezi, a izbor između stare navike i novog API-ja ovisi o tome koji od tri posla zapravo imate: primanje paketa, atribuciju toka ili zbrajanje potrošnje.
Dva načina da odgovorite na pitanje o vlasniku
Prije API 29 privilegirani ili root proces mogao je čitati kernelove tablice socketa, upariti četvorku i saznati UID vlasnika. To je davalo inventar na razini uređaja u jednoj datoteci. Od API 29 prikaz datotečnog sustava je ograničen, a podržani put je upit po vezi s protokolom, lokalnom adresom i udaljenom adresom.
| 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 |
Usporedba nije „staro protiv novog“. To su tri različita posla koja je nekad zadovoljavala jedna čitljiva datoteka, a sada ih zadovoljavaju tri različita sučelja s tri različita ugovora.
Lokalna adresa je krajnja točka aplikacije
Potpis metode prima protokol, lokalnu adresu socketa i udaljenu adresu socketa. „Lokalno“ znači stranu aplikacije u vezi, a ne onaj kraj koji se u trenutku provjere slučajno nađe kao izvor paketa. Paket koji putuje od udaljenog poslužitelja natrag prema aplikaciji ima izvor i odredište obrnute u odnosu na tu definiciju.
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);Ta greška u smjeru najčešći je razlog zašto ispravan upit vrati pogrešan odgovor ili nikakav. Zabilježite oba kraja prije poziva i provjerite par prema vezi koju je aplikacija zaista otvorila. Obitelj adresa je također važna: adresa predstavljena kroz IPv4 i izvorna IPv6 adresa različite su četvorke, kao i TCP i UDP tokovi na istim portovima.
Ovlaštenje i nepoznati rezultati dio su ugovora
Upit je ograničen na ovlaštene pozivatelje, uključujući aktivnu VPN aplikaciju za odgovarajućeg korisnika. Nepovezana aplikacija za nadzor ne može pretpostaviti da može nabrojati veze drugog profila, a neovlašten poziv može baciti sigurnosnu iznimku umjesto prijazne pogreške. Oba ishoda rješavajte eksplicitno.
Nedostajući vlasnik nije naziv paketa. Tok se mogao zatvoriti između paketa i upita, četvorka može biti nepotpuna ili pozivatelju jednostavno nije dopušteno da zna. Keširanje prvog uspješnog odgovora i njegovo kasnije korištenje pripisuje novu vezu staroj aplikaciji, što je gore od prijave nepoznatog.
Kada atribucija ne uspije, promet i dalje traži odluku: blokirajte ga gdje politika to zahtijeva, dopustite samo opseg koji razumijete ili pokažite prazninu. Taj rezervni put pripada dizajnu, ne komentaru.
Obračun je drugo pitanje
NetworkStatsManager izvještava o potrošnji po vlastitim pravilima pristupa. Može vam reći koliko je UID prenio u razdoblju; ne može reći vlasnika proizvoljnog živog paketa. Mrežne mogućnosti opisuju svojstva mreže, ne imenik socketa. Miješanje troje daje table koje izgledaju dosljedno i nisu.
Za jednostavan slučaj odlučivanja koje aplikacije koriste tunel, podržani popisi dopuštenih i zabranjenih aplikacija na Androidu već izražavaju politiku bez ikakvog struganja. Sačuvajte atribuciju po toku za slučajeve kojima zaista treba, i planirajte proračun za održavanu implementaciju koja zajedno rješava smjer, dozvole i nepoznata stanja.
Odaberite alat prema poslu, pa testirajte rubove
Ako je zahtjev odabir tunela, koristite popis platforme. Ako je riječ o atribuciji uživo, koristite upit vlasnika i svaku četvorku bez odgovora tretirajte kao nepoznatu. Ako su povijesni zbrojevi, koristite stats API. Zatim testirajte tri ruba koja lome naivne implementacije: paket u obrnutom smjeru, tok koji se zatvori prije upita i pozivatelja koji nije aktivni VPN.
Ništa od ovoga ne zahtijeva isključivanje SELinuxa, root telefona ili globalno čitljive kernel tablice. Ograničenje je poanta: platforma je premjestila atribuciju iza ugovora kako bi odgovor bio dostupan komponenti kojoj legitimno treba, i nikome drugom.