Pada Android 10 dan seterusnya, apl yang membuka /proc/net/tcp menerima penafian akses dan bukannya jadual socket. Antara muka VPN tidak peduli: paket masih tiba, kerana terowong ialah keputusan penghalaan, bukan kebenaran fail. Yang berubah ialah jawapan kepada soalan yang lebih sempit: “apl mana yang memiliki sambungan ini?” Penggantinya ialah ConnectivityManager.getConnectionOwnerUid, pertanyaan setiap sambungan yang disokong, dan pilihan antara tabiat lama dan API baharu bergantung pada tugasan mana antara tiga yang benar-benar anda ada: menerima paket, mengatribusi aliran atau menjumlahkan penggunaan.

Dua cara menjawab soalan pemilik

Sebelum API 29, proses berkeistimewaan atau root boleh membaca jadual socket kernel, memadankan empat tupel dan mengetahui UID pemilik. Itu memberi inventori seluruh peranti dalam satu fail. Sejak API 29 paparan sistem fail dihadkan, dan laluan yang disokong ialah pertanyaan setiap sambungan dengan protokol, alamat tempatan dan alamat jauh.

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

Perbandingan bukan “lama berbanding baharu”. Ia tiga tugasan berbeza yang dahulunya dipenuhi satu fail boleh baca dan kini dipenuhi tiga antara muka berbeza dengan tiga kontrak berbeza.

Alamat tempatan ialah hujung apl

Tandatangan kaedah mengambil protokol, alamat socket tempatan dan alamat socket jauh. “Tempatan” bermaksud sisi apl dalam sambungan, bukan hujung yang kebetulan menjadi sumber paket pada saat anda memeriksanya. Paket yang bergerak dari pelayan jauh kembali ke apl mempunyai sumber dan destinasi terbalik berbanding takrif itu.

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

Kesilapan arah ini ialah sebab paling biasa pertanyaan yang berfungsi mengembalikan jawapan yang salah, atau tiada. Catat kedua-dua hujung sebelum panggilan dan sahkan pasangan itu dengan sambungan yang sebenarnya dibuka oleh apl. Keluarga alamat juga penting: alamat yang dipetakan IPv4 dan alamat IPv6 asli ialah tuple berbeza, begitu juga aliran TCP dan UDP pada port yang sama.

Kebenaran dan hasil tidak diketahui sebahagian daripada kontrak

Pertanyaan terhad kepada pemanggil yang dibenarkan, termasuk apl VPN aktif untuk pengguna berkenaan. Apl pemantauan yang tidak berkaitan tidak boleh menganggap ia boleh menyenaraikan sambungan profil lain, dan panggilan tanpa kebenaran boleh melontar pengecualian keselamatan dan bukannya memulangkan ralat yang mesra. Kendalikan kedua-dua hasil secara eksplisit.

Pemilik yang tiada bukan nama pakej. Aliran mungkin telah ditutup antara paket dan pertanyaan, tuple mungkin tidak lengkap, atau pemanggil mungkin tidak dibenarkan mengetahui. Menyimpan jawapan berjaya pertama dan menggunakannya semula kemudian mengatribusikan sambungan baharu kepada apl lama, yang lebih buruk daripada melaporkan tidak diketahui.

Apabila atribusi gagal, trafik masih memerlukan keputusan: sekat di tempat dasar menghendakinya, benarkan hanya skop yang anda fahami, atau dedahkan jurang itu. Sandaran itu milik reka bentuk, bukan komen.

Perakaunan ialah soalan lain

NetworkStatsManager melaporkan penggunaan di bawah peraturan aksesnya sendiri. Ia boleh memberitahu berapa banyak yang dipindahkan oleh UID dalam satu tempoh; ia tidak boleh memberitahu pemilik paket hidup yang sewenang-wenangnya. Keupayaan rangkaian menerangkan sifat rangkaian, bukan direktori socket. Mencampurkan ketiga-tiganya menghasilkan papan pemuka yang kelihatan konsisten dan sebenarnya tidak.

Untuk kes mudah menentukan apl mana yang menggunakan terowong, senarai apl dibenarkan dan dilarang yang disokong Android sudah menyatakan dasar itu tanpa mengikis apa-apa. Simpan atribusi setiap aliran untuk kes yang benar-benar memerlukannya, dan belanjakan untuk pelaksanaan terpelihara yang mengendalikan arah, kebenaran dan keadaan tidak diketahui bersama-sama.

Pilih alat mengikut tugasan, kemudian uji tepinya

Jika keperluan ialah pemilihan terowong, gunakan senarai platform. Jika atribusi langsung, gunakan pertanyaan pemilik dan anggap setiap tuple yang tidak dapat dijawab sebagai tidak diketahui. Jika jumlah sejarah, gunakan stats API. Kemudian uji tiga tepi yang mematahkan pelaksanaan naif: paket arah bertentangan, aliran yang menutup sebelum anda bertanya, dan pemanggil yang bukan VPN aktif.

Tiada satu pun daripada ini memerlukan penyahaktifan SELinux, root telefon atau jadual kernel boleh dibaca secara global. Kekangan itulah maksudnya: platform memindahkan atribusi di sebalik kontrak supaya jawapannya tersedia kepada komponen yang benar-benar memerlukannya secara sah, dan kepada tiada orang lain.

Artikel berkaitan