Android VPN-atribuado: getConnectionOwnerUid kontraŭ /proc/net
Android 10 kaŝas /proc/net por aplikaĵoj. VPN ankoraŭ ricevas pakaĵojn, sed atribuado translokiĝas al getConnectionOwnerUid, kun propraj reguloj pri tuple kaj permesoj.
En Android 10 kaj pli nova, aplikaĵo kiu malfermas /proc/net/tcp ricevas alirrifuzon anstataŭ soketan tabelon. La VPN-interfaco ne zorgas: pakaĵoj ankoraŭ alvenas, ĉar la tunelo estas enkursiga decido, ne dosiera permeso. Kio ŝanĝiĝis estas la respondo al pli mallarĝa demando: «kiu aplikaĵo posedas ĉi tiun konekton?» La anstataŭaĵo estas ConnectivityManager.getConnectionOwnerUid, la subtenata demando po konekto, kaj la elekto inter la malnova kutimo kaj la nova API dependas de tio, kiun el tri taskoj vi efektive havas: ricevi pakaĵojn, atribui fluon aŭ sumi uzadon.
Du manieroj respondi la posedantan demandon
Antaŭ API 29, privilegia aŭ root-procezo povis legi la soketajn tabelojn de la kerno, kongrui la kvaropon kaj ekscii la posedan UID. Tio donis inventaron por la tuta aparato en unu dosiero. Ekde API 29 la dosiersistema vido estas limigita, kaj la subtenata vojo estas demando po konekto kun la protokolo, la loka adreso kaj la fora adreso.
| 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 |
La komparo ne estas «malnova kontraŭ nova». Ĝi estas tri malsamaj taskoj, kiujn antaŭe plenumis unu legebla dosiero kaj nun plenumas tri malsamaj interfacoj kun tri malsamaj kontraktoj.
La loka adreso estas la finpunkto de la aplikaĵo
La metodsubskribo prenas protokolon, lokan soketan adreson kaj foran soketan adreson. «Loka» signifas la flankon de la aplikaĵo en la konekto, ne tiun finpunkton, kiu hazarde estas la fonto de la pakaĵo en la momento de la kontrolo. Pakaĵo vojaĝanta de la fora servilo reen al la aplikaĵo havas sian fonton kaj celon inversigitaj rilate al tiu difino.
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);Ĉi tiu direkta eraro estas la plej ofta kialo, ke funkcianta demando donas malĝustan respondon aŭ neniun. Registru ambaŭ finpunktojn antaŭ la voko kaj konfirmu la paron kontraŭ la konekto, kiun la aplikaĵo efektive malfermis. Ankaŭ la adresa familio gravas: IPv4-mapita adreso kaj denaska IPv6-adreso estas malsamaj kvaropoj, same kiel TCP- kaj UDP-fluoj sur la samaj pordoj.
Rajtigo kaj nekonataj rezultoj estas parto de la kontrakto
La demando limiĝas al rajtigitaj vokantoj, inkluzive de la aktiva VPN-aplikaĵo por la koncerna uzanto. Neligita monitora aplikaĵo ne povas supozi, ke ĝi povas listigi la konektojn de alia profilo, kaj nerajtigita voko povas ĵeti sekurecan escepton anstataŭ afablan eraron. Traktu ambaŭ rezultojn eksplicite.
Mankanta posedanto ne estas pakaĵnomo. La fluo eble fermiĝis inter la pakaĵo kaj la demando, la kvaropo eble nekompletas, aŭ la vokanto simple ne rajtas scii. Kaŝi la unuan sukcesan respondon kaj reuzi ĝin poste atribuas novan konekton al malnova aplikaĵo, kio estas pli malbona ol raporti nekonaton.
Kiam atribuado malsukcesas, la trafiko ankoraŭ bezonas decidon: bloki ĝin kie la politiko postulas, permesi nur amplekson kiun vi komprenas, aŭ montri la breĉon. Tiu rezerva vojo apartenas al la dezajno, ne al komento.
Librotenado estas alia demando
NetworkStatsManager raportas uzadon laŭ propraj alirreguloj. Ĝi povas diri kiom UID transigis dum periodo; ĝi ne povas diri la posedanton de arbitra vivanta pakaĵo. Retaj kapabloj priskribas ecojn de reto, ne dosierujon de soketoj. Miksi la tri produktas panelojn, kiuj aspektas konsekvencaj kaj ne estas.
Por la simpla kazo decidi, kiuj aplikaĵoj uzas la tunnelon, la subtenataj listoj de permesitaj kaj malpermesitaj aplikaĵoj de Android jam esprimas la politikon sen ia skrapado. Konservu atribuadon po fluo por la kazoj, kiuj vere bezonas ĝin, kaj buĝetu por prizorgata efektivigo, kiu traktas direkton, permesojn kaj nekonatajn statojn kune.
Elektu la ilon laŭ tasko, poste testu la randojn
Se la postulo estas tunela elekto, uzu la platforman liston. Se temas pri viva atribuado, uzu la posedantan demandon kaj traktu ĉiun neresponeblan kvaropon kiel nekonatan. Se temas pri historiaj sumoj, uzu la stats API. Poste testu la tri randojn, kiuj rompas naivajn efektivigojn: pakaĵo en la kontraŭa direkto, fluo kiu fermiĝas antaŭ ol vi demandas, kaj vokanto kiu ne estas la aktiva VPN.
Nenio el tio postulas malŝalti SELinux, radikigi la telefonon aŭ igi kernajn tabelojn tutmonde legeblaj. La limigo estas la senco: la platformo movis atribuadon malantaŭ kontrakto, por ke la respondo estu disponebla al la komponanto, kiu laŭleĝe bezonas ĝin, kaj al neniu alia.