Di Android 10 dan setelahnya, aplikasi yang membuka /proc/net/tcp mendapat penolakan akses alih-alih tabel socket. Antarmuka VPN tidak peduli: paket tetap datang, karena tunnel adalah keputusan perutean, bukan izin berkas. Yang berubah adalah jawaban atas pertanyaan yang lebih sempit: “aplikasi mana yang memiliki koneksi ini?” Penggantinya adalah ConnectivityManager.getConnectionOwnerUid, kueri per koneksi yang didukung, dan memilih antara kebiasaan lama dan API baru bergantung pada mana dari tiga pekerjaan yang benar-benar Anda miliki: menerima paket, mengatribusikan aliran, atau menjumlahkan pemakaian.

Dua cara menjawab pertanyaan pemilik

Sebelum API 29, proses dengan hak istimewa atau root dapat membaca tabel socket kernel, mencocokkan empat-tuple, dan mengetahui UID pemiliknya. Itu memberikan inventaris seluruh perangkat dalam satu berkas. Sejak API 29, tampilan sistem berkas dibatasi, dan jalur yang didukung adalah kueri per koneksi dengan protokol, alamat lokal, dan alamat jarak 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

Perbandingannya bukan “lama versus baru”. Ini tiga pekerjaan berbeda yang dulu dipenuhi satu berkas yang dapat dibaca dan kini dipenuhi tiga antarmuka berbeda dengan tiga kontrak berbeda.

Alamat lokal adalah ujung aplikasi

Tanda tangan metode menerima protokol, alamat socket lokal, dan alamat socket jarak jauh. “Lokal” berarti sisi aplikasi dalam koneksi, bukan ujung yang kebetulan menjadi sumber paket saat Anda memeriksanya. Paket yang bergerak dari server jarak jauh kembali ke aplikasi memiliki sumber dan tujuan terbalik terhadap definisi itu.

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

Kesalahan arah ini adalah alasan paling umum sebuah kueri yang berfungsi mengembalikan jawaban yang salah, atau tidak sama sekali. Catat kedua ujung sebelum panggilan dan cocokkan pasangan itu dengan koneksi yang benar-benar dibuka aplikasi. Keluarga alamat juga penting: alamat yang dipetakan IPv4 dan alamat IPv6 asli adalah tuple berbeda, begitu pula aliran TCP dan UDP pada port yang sama.

Otorisasi dan hasil tak dikenal adalah bagian dari kontrak

Kueri dibatasi pada pemanggil yang berwenang, termasuk aplikasi VPN aktif untuk pengguna terkait. Aplikasi pemantauan yang tidak berkepentingan tidak dapat menganggap dirinya dapat menghitung koneksi profil lain, dan panggilan tanpa izin dapat melempar pengecualian keamanan alih-alih mengembalikan kesalahan yang ramah. Tangani kedua hasil secara eksplisit.

Pemilik yang hilang bukan nama paket. Aliran mungkin sudah ditutup antara paket dan kueri, tuple mungkin tidak lengkap, atau pemanggil memang tidak diizinkan mengetahuinya. Menyimpan jawaban sukses pertama dan memakainya lagi nanti mengatribusikan koneksi baru ke aplikasi lama, yang lebih buruk daripada melaporkan tidak diketahui.

Ketika atribusi gagal, lalu lintas tetap butuh keputusan: blokir di tempat kebijakan mensyaratkannya, izinkan hanya cakupan yang Anda pahami, atau tampilkan celahnya. Cadangan itu bagian dari desain, bukan komentar.

Akuntansi adalah pertanyaan lain

NetworkStatsManager melaporkan pemakaian menurut aturan aksesnya sendiri. Ia dapat memberi tahu berapa banyak yang ditransfer sebuah UID selama suatu periode; ia tidak dapat memberi tahu pemilik paket hidup yang sembarang. Kemampuan jaringan menjelaskan sifat jaringan, bukan direktori socket. Mencampur ketiganya menghasilkan dasbor yang tampak konsisten dan tidak.

Untuk kasus sederhana menentukan aplikasi mana yang memakai tunnel, daftar aplikasi yang diizinkan dan dilarang yang didukung Android sudah menyatakan kebijakan tanpa mengikis apa pun. Sisakan atribusi per aliran untuk kasus yang benar-benar membutuhkannya, dan anggarkan implementasi terpelihara yang menangani arah, izin, dan keadaan tak dikenal sekaligus.

Pilih alat menurut pekerjaan, lalu uji tepinya

Jika persyaratannya pemilihan tunnel, gunakan daftar platform. Jika atribusi langsung, gunakan kueri pemilik dan perlakukan setiap tuple yang tak terjawab sebagai tak dikenal. Jika total historis, gunakan stats API. Lalu uji tiga tepi yang mematahkan implementasi naif: paket arah sebaliknya, aliran yang menutup sebelum Anda bertanya, dan pemanggil yang bukan VPN aktif.

Tidak ada dari ini yang memerlukan menonaktifkan SELinux, melakukan root pada ponsel, atau membuat tabel kernel terbaca global. Batasannya justru intinya: platform memindahkan atribusi ke balik kontrak agar jawabannya tersedia bagi komponen yang sah membutuhkannya, dan bagi tidak seorang pun lainnya.

Artikel terkait