Mengapa Android VpnService Menangkap Sebahagian Trafik dan Bukan Semua
Laluan, entri DNS dan skop setiap aplikasi menentukan paket mana yang sampai ke peranti tun, mengapa peranti setempat hilang dan apa yang ditolak pembina.
Tiada apa-apa dalam VpnService memintas trafik dengan sendirinya. Ia meminta antara muka tun daripada sistem, menyerahkan satu set alamat dan laluan kepada antara muka itu, dan dari saat itu kernel menyalin setiap paket yang sepadan dengan laluan itu ke dalam deskriptor fail yang boleh dibaca oleh aplikasi. Kod aplikasi tidak pernah melihat paket yang tidak dipilih oleh laluan, jadi skop terowong ialah persoalan jadual penghalaan sebelum ia menjadi persoalan pengaturcaraan. Itulah sebabnya pelaksanaan perkhidmatan yang sama boleh menelan setiap aliran pada satu telefon dan hanya sebahagian pada telefon lain, dan itulah sebabnya menambah laluan kadangkala membaiki terowong yang kelihatan rosak. Yang anda dapat ialah yang anda isytiharkan, tolak apa sahaja yang ditolak pembina secara senyap.
Laluan menentukan paket mana yang tiba
Builder.addRoute(prefix, prefixLength) memasang awalan ke dalam jadual penghalaan rangkaian VPN. Sistem menganggap rangkaian itu sebagai lalai untuk aplikasi dalam skop, jadi entrinya dirujuk sebelum laluan lalai rangkaian fizikal dan awalan yang sepadan sudah cukup untuk memesongkan aliran. Oleh itu laluan untuk 0.0.0.0/0 mengambil IPv4 sepenuhnya, termasuk pencetak, sasaran cast dan halaman pentadbir penghala.
Klien yang mahukan liputan itu tanpa memadam entri lalai fizikal menggunakan pasangan 0.0.0.0/1 dan 128.0.0.0/1 pula. Dua laluan yang lebih khusus mengalahkan laluan lalai, bersama-sama ia meliputi seluruh ruang alamat, dan entri lalai telefon itu sendiri kekal dalam jadual untuk soket yang masih terikat pada rangkaian fizikal.
Alamat dan entri DNS datang daripada pembina yang sama dan menjawab soalan yang berbeza. addAddress memberikan antara muka alamat dengan panjang awalan, dan addDnsServer memasang penyelesai yang akan ditanya oleh aplikasi dalam skop melalui antara muka. Kedua-dua keluarga boleh duduk pada satu antara muka, jadi set laluan hanya IPv4 di sebelah alamat IPv6 ialah konfigurasi yang dibaca dengan betul dan masih bocor. Jika anda menghala keluarga yang tiada alamat pada antara muka, kernel tiada alamat sumber untuk paket itu dan ia tidak pernah muncul pada deskriptor.
Apa yang establish() pulangkan
establish() memulangkan ParcelFileDescriptor, atau null apabila aplikasi tidak dibenarkan. Null ialah keadaan persetujuan, bukan ralat rangkaian: VpnService.prepare() sepatutnya sudah memulangkan null, atau pengguna sepatutnya telah meluluskan dialog sistem sebelum panggilan. Persetujuan boleh ditarik balik semasa perkhidmatan berjalan, dan antara muka tertutup di bawah kaki anda tanpa sebarang panggilan balik ke gelung bacaan anda.
Deskriptor tidak menyekat melainkan anda menyatakan sebaliknya, jadi bacaan kembali serta-merta tanpa data dan bukannya meletakkan benang di parkir. Gelung yang ditulis untuk soket menyekat membakar satu teras, dan gelung yang menganggap bacaan kosong sebagai maut merobek terowong dalam satu saat melahu. Builder.setBlocking(true) mengubah tingkah laku itu, dan harganya ialah benang yang menunggu di dalam bacaan.
Argumen laluan dan alamat disahkan sebagai nilai LinkAddress, dan destinasi multicast seperti 224.0.0.0/4 ditolak secara terus. Antara muka tun titik-ke-titik juga tiada domain siaran, jadi penemuan multicast melaluinya memerlukan reka bentuk lain dan bukannya satu lagi laluan. Rujukan VpnService.Builder ialah senarai yang perlu diperiksa sebelum anda membuat kesimpulan bahawa sesuatu panggilan diabaikan.
Skop setiap aplikasi menyempitkan set, bukan terowong
Sejak API 21 pembina menerima addAllowedApplication dan addDisallowedApplication, dan kedua-dua senarai saling eksklusif dalam satu pembina. Senarai benarkan menjadikan terowong wujud untuk paket itu sementara semua yang lain mengekalkan rangkaian fizikal; senarai larang menangkap segala-galanya kecuali paket yang dinamakan, yang ditawarkan klien sebagai terowong berpecah. Sebelum API 21 tiada mekanisme platform sama sekali, dan tingkah laku setiap aplikasi datang daripada klien pihak ketiga yang menapis mengikut UID di dalam penghantar mereka sendiri. Perbezaan ini penting semasa nyahpepijat, kerana terowong setiap aplikasi dengan senarai benarkan satu paket hampir tidak menghasilkan trafik dan itu tingkah laku yang betul, bukan laluan yang rosak.
Apa pun skopnya, soket yang dibuka aplikasi anda ke pelayan VPN tidak boleh melalui terowong yang sedang dibinanya. VpnService.protect(socket) mengikat soket itu kepada rangkaian asas supaya paketnya melangkau peranti tun. Jika anda melangkau panggilan itu, jabat tangan ditelan oleh antara muka yang sepatutnya menaikkannya.
VpnService.setUnderlyingNetworks menutup gelung dengan memberitahu sistem rangkaian fizikal mana yang membawa terowong. Nilai itu menentukan cara VPN melaporkan ketersambungan kepada aplikasi lain, dan nilai null atau lapuk ialah punca biasa terowong bersambung yang dianggap telefon selebihnya sebagai luar talian. Kemas kininya apabila rangkaian asas berubah, bukan hanya semasa permulaan.
Semak jumlah dan MTU: di mana laluan yang betul masih gagal
Sebaik sahaja paket tiba, dua perincian pada peringkat paket menentukan sama ada sesuatu berfungsi dari hujung ke hujung. Yang pertama ialah alamat sumber: dengan beberapa alamat antara muka kernel boleh mengeluarkan paket yang membawa yang pertama, jadi penghantar yang menulis semula pengepala mesti membetulkan alamat dan semak jumlah yang meliputinya.
Yang kedua ialah skop semak jumlah. Apabila aplikasi membina paket TCP atau UDP sendiri, semak jumlah meliputi pengepala pseudo yang memegang alamat sumber, alamat destinasi, nombor protokol dan panjang pengangkutan, dan meninggalkan mana-mana satu daripadanya menghasilkan paket yang tiba lalu dibuang. Kegagalan itu kelihatan seperti tamat masa selepas balasan yang tidak pernah datang, yang menghantar kebanyakan orang kembali kepada laluan. setMtu menetapkan MTU antara muka, dan setiap bacaan memulangkan tepat satu paket IP lengkap, jadi penimbal yang ditulis untuk aliran bait akan memecahkan penghuraian anda, bukan paketnya.
Satu pusingan pengesahan yang memisahkan lapisan
Untuk mencari di mana skop tersasar, uji lapisan mengikut urutan. Tanya peranti laluan mana yang sebenarnya dipegang oleh rangkaian VPN, kemudian semak sama ada aliran ke alamat yang diketahui muncul sebagai bacaan pada deskriptor, kemudian semak sama ada paket yang dikeluarkan penghantar anda terbentuk dengan baik. Masalah laluan tidak menunjukkan apa-apa pada deskriptor, manakala masalah semak jumlah menunjukkan paket yang tiba dan lenyap.
Jika tiada apa-apa sampai ke deskriptor, yang disyaki ialah set laluan dan bukan pembaca: sahkan awalannya, sahkan ada alamat dalam keluarga yang sama, dan sahkan aplikasi berada dalam skop yang anda tetapkan. Jika paket sampai ke deskriptor tetapi tiada apa-apa kembali, periksa protect() dan nilai rangkaian asas sebelum menyentuh laluan lagi. Jika sebelah jauh melaporkan paket cacat, semak jumlah dan MTU ialah tempat untuk melihat. Satu siasatan setiap lapisan menjimatkan satu petang meneka.