Android 10 és újabb rendszereken a /proc/net/tcp megnyitó alkalmazás hozzáférés-megtagadást kap socket-tábla helyett. A VPN-interfészt ez nem érdekli: a csomagok továbbra is megérkeznek, mert az alagút útválasztási döntés, nem fájljogosultság. Ami megváltozott, az a válasz egy szűkebb kérdésre: „melyik alkalmazás birtokolja ezt a kapcsolatot?” A helyettesítő a ConnectivityManager.getConnectionOwnerUid, a támogatott kapcsolatonkénti lekérdezés, és a választás a régi szokás és az új API között attól függ, melyik a három feladat közül van valójában: csomagok fogadása, folyam attribúciója vagy használat összegzése.

Két mód a tulajdonos kérdésének megválaszolására

Az API 29 előtt egy kiváltságos vagy root folyamat olvashatta a kernel socket-tábláit, egyeztethette a négyest, és megtudhatta a birtokló UID-t. Ez egyetlen fájlban adott eszközszintű leltárt. Az API 29-től a fájlrendszer-nézet korlátozott, és a támogatott út a kapcsolatonkénti lekérdezés a protokollal, a helyi címmel és a távoli címmel.

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

Az összehasonlítás nem „régi kontra új”. Három különböző feladatról van szó, amelyeket korábban egy olvasható fájl elégített ki, most pedig három különböző interfész három különböző szerződéssel.

A helyi cím az alkalmazás végpontja

A metódus szignatúrája protokollt, helyi socket-címet és távoli socket-címet vesz át. A „helyi” a kapcsolat alkalmazás oldalát jelenti, nem azt a végpontot, amely az ellenőrzés pillanatában épp a csomag forrása. A távoli szerverről az alkalmazás felé visszatérő csomag forrása és célja ehhez a meghatározáshoz képest felcserélődött.

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

Ez az irányhiba a leggyakoribb oka annak, hogy egy működő lekérdezés rossz választ ad, vagy semmit. Naplózza mindkét végpontot a hívás előtt, és ellenőrizze a párt ahhoz a kapcsolathoz, amelyet az alkalmazás valóban megnyitott. A címcsalád is számít: az IPv4-címkézett cím és a natív IPv6-cím különböző tuple, csakúgy, mint az azonos portokon futó TCP- és UDP-folyamok.

Az engedélyezés és az ismeretlen eredmények a szerződés részei

A lekérdezés engedélyezett hívókra korlátozódik, beleértve az érintett felhasználó aktív VPN-alkalmazását. Egy független megfigyelő alkalmazás nem feltételezheti, hogy felsorolhatja egy másik profil kapcsolatait, és egy jogosulatlan hívás biztonsági kivételt dobhat barátságos hiba helyett. Mindkét kimenetet kezelje kifejezetten.

A hiányzó tulajdonos nem csomagnév. A folyam bezárulhatott a csomag és a lekérdezés között, a tuple hiányos lehet, vagy egyszerűen nem engedélyezett a hívónak tudni. Az első sikeres válasz gyorsítótárazása és későbbi újrafelhasználása új kapcsolatot rendel egy régi alkalmazáshoz, ami rosszabb, mint ismeretlent jelenteni.

Amikor az attribúció meghiúsul, a forgalomnak még döntés kell: blokkolja ott, ahol a szabályzat megköveteli, csak általa értett hatókört engedélyezzen, vagy tárja fel a hiányt. Ez a tartalék a tervezéshez tartozik, nem egy megjegyzéshez.

Az elszámolás más kérdés

NetworkStatsManager saját hozzáférési szabályai szerint jelent használatot. Meg tudja mondani, mennyit továbbított egy UID egy időszak alatt; nem tudja megmondani egy tetszőleges élő csomag tulajdonosát. A hálózati képességek egy hálózat tulajdonságait írják le, nem socketek könyvtárát. A három keverése konzisztensnek tűnő, de nem az irányítópultokat eredményez.

Az egyszerű esetben, amikor eldönti, mely alkalmazások használják az alagutat, az Android támogatott engedélyezett és tiltott alkalmazáslistái már scraping nélkül kifejezik a szabályzatot. Tartsa meg a folyamonkénti attribúciót azokra az esetekre, amelyeknek valóban szüksége van rá, és tervezzen költséget egy karbantartott megvalósításra, amely az irányt, az engedélyeket és az ismeretlen állapotokat együtt kezeli.

Válassza ki az eszközt feladat szerint, majd tesztelje az éleket

Ha a követelmény az alagút kiválasztása, használja a platform listáját. Ha élő attribúció, használja a tulajdonos lekérdezését, és minden megválaszolhatatlan tuple-t tekintsen ismeretlennek. Ha történelmi összegek, használja a stats API-t. Utána tesztelje a három élt, amely megtöri a naiv megvalósításokat: ellenkező irányú csomag, a lekérdezés előtt bezáruló folyam, és olyan hívó, amely nem az aktív VPN.

Ezek egyike sem igényli a SELinux letiltását, a telefon rootolását vagy a kerneltáblák globálisan olvashatóvá tételét. A korlátozás a lényeg: a platform egy szerződés mögé helyezte az attribúciót, hogy a válasz elérhető legyen annak a komponensnek, amelynek jogosan szüksége van rá, és senki másnak.

Kapcsolódó cikkek