Anggapan yang keliru adalah bahwa aplikasi VpnService membalik sakelar sistem dan sejak itu ponsel terlindungi. Yang sebenarnya terjadi lebih sempit: aplikasi meminta persetujuan, membangun antarmuka, membaca dan menulis paket melalui deskriptor berkas, dan mengembalikan antarmuka saat berhenti. Hanya satu terowongan seperti itu yang bisa hidup pada satu waktu, dan sistem dapat mengambilnya tanpa bertanya. Sebagian besar perilaku membingungkan yang disalahkan orang pada protokol berasal dari model kepemilikan itu.

Perlakukan setiap transisi siklus hidup sebagai bagian dari desain, bukan sebagai kasus tepi.

Mitos: aplikasi menyalakan VPN ponsel

Alur dimulai dengan VpnService.prepare(), yang mengembalikan Intent yang harus diterima pengguna, dan berlanjut dengan establish(), yang setelah itu masih bisa gagal karena alasan yang tidak dikendalikan aplikasi. Membangun terowongan kedua menonaktifkan antarmuka pertama dan menggantikan notifikasi sistem. Tidak di mana pun dalam urutan itu aplikasi memiliki sakelar untuk seluruh perangkat; ia memiliki deskriptor yang diberikan kepadanya dan paket yang mendarat di atasnya. Bahkan notifikasi permanen milik sistem, bukan milik desain aplikasi.

Karena antarmuka diberikan bukan direbut, klien lain dapat mengambil tempat itu kapan saja. Aplikasi mengetahuinya lewat panggilan balik, bukan lewat nilai kembalian.

Penghentian paksa aplikasi terlihat di panel notifikasi karena alasan yang sama: sistem melaporkan apa yang diberikannya, bukan apa yang dipilih aplikasi untuk ditampilkan.

Mitos: persetujuan diberikan sekali

Ketika sistem menyerahkan terowongan ke klien lain, ia mengirim transaksi pencabutan pada binder yang dikembalikan kelas dasar dari onBind(). Aplikasi yang mengganti binder itu dengan miliknya sendiri harus meneruskan transaksi pencabutan sendiri, jika tidak VpnService.onRevoke() tidak pernah terpicu dan layanan terus menulis ke deskriptor yang sudah tidak ada. Persetujuan juga bisa dicabut pengguna, dan sistem dapat menghentikan layanan saat mulai ulang atau penyambungan kembali selalu aktif.

Menanganinya adalah pekerjaan konkret, bukan satu baris log: berhenti membaca deskriptor, tutup, bersihkan tanda terhubung, dan beri tahu pengguna di status mana mereka berada. Lalu putuskan apakah aplikasi harus membangun ulang, bertanya lagi, atau menunggu, karena dalam konfigurasi selalu aktif sistem dapat mengembalikan layanan sendiri.

Aplikasi yang memperlakukan pencabutan sebagai pengecualian dan bukan sebagai keadaan akan melaporkan terhubung sementara setiap paket yang ditulisnya dibuang, dan itu adalah mode kegagalan terburuk bagi alat privasi.

Mitos: antarmuka menyaring lalu lintas untuk Anda

Yang datang adalah IP mentah. Menangkap atau menyaring berarti mengurai header IP, TCP, UDP, dan IPv6, melacak aliran, dan menulis balasan kembali ke deskriptor, yang menjadikan aplikasi penangkap sebagai tumpukan jaringan kecil, bukan fasilitas sistem. protect() ada agar socket transport aplikasi sendiri melewati terowongannya alih-alih menangkap dirinya sendiri, dan ia mengembalikan boolean yang layak diperiksa pada setiap socket yang dibuat setelah terowongan aktif.

Daftar aplikasi yang diizinkan dan dilarang di builder menentukan lalu lintas siapa yang masuk ke antarmuka. Mereka tidak memberikan akses ke muatan di luar paket IP yang dibawa antarmuka, dan tidak ada API yang menyingkap terowongan klien lain atau mendaftar profil VPN sistem. Kemampuan jaringan dapat mengatakan bahwa suatu jaringan adalah transport VPN, tetapi bukan milik siapa terowongan itu.

Itulah sebabnya pertanyaan status tentang aplikasi lain mendapat jawaban yang bertentangan: informasinya memang tidak diekspos ke proses Anda.

Apa yang sebenarnya dituntut siklus hidup

Lacak keadaan yang Anda kendalikan: siap, terbangun, dicabut, dihentikan. Penyambungan kembali seharusnya berupa pembongkaran lalu pembangunan, dengan satu pemilik untuk deskriptor dan socket transport, karena dua komponen yang berlomba membangun akan berebut satu tempat yang tersedia. Mulai di latar belakang dibatasi di Android modern, jadi siaran boot bukan jaminan; gunakan layanan latar depan dengan notifikasinya di tempat level API mengizinkan.

Catat transisinya, bukan hanya keadaan akhirnya, dan jaga mesin keadaan cukup kecil untuk menguji setiap jalur. Keadaan yang tidak dapat Anda capai dalam pengujian adalah keadaan yang akan Anda temui di lapangan tanpa log.

Uji siklus hidup di perangkat

Emulator dapat memalsukan konektivitas tetapi tidak jalur persetujuan dan pencabutan secara meyakinkan, jadi jalankan ini di perangkat nyata dengan klien VPN kedua terpasang untuk mencuri tempatnya.

adb shell dumpsys connectivity | grep -i -A3 vpn
adb shell dumpsys activity services | grep -i -A2 vpnservice
adb logcat -s VpnService:V AndroidRuntime:E
adb shell am force-stop com.example.vpnapp

Mulai terowongan, pastikan notifikasi dan antarmukanya, lalu sambungkan klien lain dan amati apakah panggilan balik pencabutan berjalan dan keadaannya bersih. Hentikan paksa aplikasi dan periksa apakah ada yang masih melaporkan deskriptor yang hidup.

Ulangi urutan setelah mulai ulang selalu aktif, karena jalur itu berbeda dari sambungan yang dimulai pengguna. Yang Anda cari bukan ikon hijau melainkan bukti bahwa aplikasi berhenti menggunakan deskriptor yang bukan lagi miliknya.

Artikel terkait