V Androidu 10 a novějším dostane aplikace, která otevře /proc/net/tcp, odmítnutí přístupu místo tabulky socketů. VPN rozhraní to nezajímá: pakety dál přicházejí, protože tunel je rozhodnutí o směrování, ne souborové oprávnění. Změnila se odpověď na užší otázku: „která aplikace vlastní toto spojení?“ Náhradou je ConnectivityManager.getConnectionOwnerUid, podporovaný dotaz na spojení, a volba mezi starým zvykem a novým API závisí na tom, který ze tří úkolů skutečně máte: přijímat pakety, atribuovat tok nebo sčítat spotřebu.

Dva způsoby, jak odpovědět na otázku vlastníka

Před API 29 mohl privilegovaný nebo root proces číst tabulky socketů jádra, spárovat čtveřici a zjistit vlastnící UID. To dávalo inventář celého zařízení v jednom souboru. Od API 29 je pohled na souborový systém omezený a podporovanou cestou je dotaz na spojení s protokolem, lokální adresou a vzdálenou adresou.

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

Srovnání není „staré proti novému“. Jsou to tři různé úkoly, které dřív uspokojoval jeden čitelný soubor a dnes je uspokojují tři různá rozhraní se třemi různými kontrakty.

Lokální adresa je konec aplikace

Signatura metody bere protokol, lokální adresu socketu a vzdálenou adresu socketu. „Lokální“ znamená stranu aplikace ve spojení, ne ten konec, který se v okamžiku kontroly náhodou stal zdrojem paketu. Paket putující ze vzdáleného serveru zpět k aplikaci má zdroj a cíl vůči této definici obrácené.

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

Tato chyba směru je nejčastějším důvodem, proč funkční dotaz vrátí špatnou odpověď nebo žádnou. Zalogujte oba konce před voláním a ověřte dvojici proti spojení, které aplikace skutečně otevřela. Na rodině adres také záleží: adresa mapovaná přes IPv4 a nativní adresa IPv6 jsou různé čtveřice, stejně jako toky TCP a UDP na stejných portech.

Autorizace a neznámé výsledky jsou součástí kontraktu

Dotaz je omezen na oprávněné volající, včetně aktivní VPN aplikace pro příslušného uživatele. Nesouvisející monitorovací aplikace nemůže předpokládat, že vypíše spojení jiného profilu, a neoprávněné volání může vyhodit bezpečnostní výjimku místo přátelské chyby. Oba výsledky řešte explicitně.

Chybějící vlastník není název balíčku. Tok se mohl uzavřít mezi paketem a dotazem, čtveřice může být neúplná nebo volajícímu prostě není dovoleno to vědět. Ukládání první úspěšné odpovědi a její pozdější použití přiřadí nové spojení staré aplikaci, což je horší než hlásit neznámo.

Když atribuce selže, provoz stejně potřebuje rozhodnutí: zablokovat tam, kde to politika vyžaduje, povolit jen rozsah, kterému rozumíte, nebo ukázat mezeru. Tento záložní postup patří do návrhu, ne do komentáře.

Účtování je jiná otázka

NetworkStatsManager hlásí spotřebu podle vlastních pravidel přístupu. Může říct, kolik UID přenesl za období; nemůže říct vlastníka libovolného živého paketu. Schopnosti sítě popisují vlastnosti sítě, ne adresář socketů. Míchání tří věcí dává dashboardy, které vypadají konzistentně a nejsou.

Pro jednoduchý případ rozhodnutí, které aplikace používají tunel, už podporované seznamy povolených a zakázaných aplikací v Androidu vyjadřují politiku bez jakéhokoli scrapování. Atribuci po toku si nechte pro případy, které ji skutečně potřebují, a počítejte s udržovanou implementací, která řeší směr, oprávnění i neznámé stavy společně.

Vyberte nástroj podle úkolu, pak testujte okraje

Pokud je požadavkem volba tunelu, použijte seznam platformy. Pokud jde o živou atribuci, použijte dotaz na vlastníka a každou čtveřici bez odpovědi berte jako neznámou. Pokud jde o historické součty, použijte stats API. Pak otestujte tři okraje, které lámou naivní implementace: paket v opačném směru, tok, který se uzavře před dotazem, a volajícího, který není aktivní VPN.

Nic z toho nevyžaduje vypnutí SELinuxu, root telefonu ani globálně čitelné tabulky jádra. Omezení je pointa: platforma přesunula atribuci za kontrakt, aby odpověď byla dostupná komponentě, která ji legitimně potřebuje, a nikomu jinému.

Související články