Ponsel melakukan boot ulang, always-on aktif, «blokir koneksi tanpa VPN» menyala, dan tunnel tidak pernah muncul. Tidak ada yang salah konfigurasi: pemblokiran menjalankan tugasnya, dan upaya klien sendiri untuk mencapai endpoint-nya tunduk pada pemblokiran itu. Nama endpoint harus diresolusi sebelum tunnel ada, oleh klien yang diizinkan berbicara dengan jaringan sementara semua aplikasi lain tidak. Memahami komponen mana yang melakukannya, dan dalam urutan apa, adalah yang mengubah teka-teki ini menjadi pertanyaan konfigurasi.

Apa yang sebenarnya diminta pembangun VPN

Aplikasi VPN Android tidak menyerahkan alamat server kepada platform. Ia membangun antarmuka lokal: alamat dan rute untuk tunnel, resolver yang harus dipakai aplikasi di dalamnya, lalu establish() mengembalikan deskriptor berkas yang dibaca dan ditulis aplikasi sebagai paket IP mentah. Endpoint jarak jauh sama sekali tidak muncul di pembangun itu.

Itulah fakta struktural kuncinya. Platform membuat antarmuka tun dan menegakkan kebijakan di atasnya; aplikasi mengimplementasikan transport di ruang pengguna, yang berarti aplikasi itu sendiri yang meresolusi nama endpoint-nya dan membuka koneksi terenkripsi. Endpoint berupa nama host karena itu mungkin — bukan karena platform mendukung nama, tetapi karena platform tidak pernah melihat endpoint.

Satu bidang pembangun memang menerima alamat: server DNS. Alamat itu harus berupa alamat resolver numerik, biasanya yang ingin ditanyakan operator melalui tunnel. Bidang itu menjelaskan ke mana aplikasi mengirim kueri setelah tunnel menyala. Ia tidak mengatakan apa pun tentang bagaimana klien menemukan endpoint, dan memperlakukan keduanya sebagai pengaturan yang sama adalah awal dari kebingungan.

Dua pertanyaan DNS, bukan satu

Pertanyaan pertama: ke mana aplikasi mengirim kueri setelah tunnel menyala? Jawabannya adalah alamat resolver di dalam tunnel, terjangkau melalui antarmuka tun, dan secara konstruksi bersifat numerik.

Pertanyaan kedua: bagaimana klien menemukan endpoint-nya sendiri sebelum tunnel itu ada? Pencarian itu terjadi di luar tunnel, pada jaringan yang mendasarinya, di dalam proses klien. Ia boleh memakai nama, dan ia harus memakai resolver yang dapat dijangkau perangkat tanpa VPN.

StageWho resolvesPathFailure looks like
Endpoint lookupThe VPN appUnderlying network, protected socketNever connects; no tunnel interface traffic
Peer authenticationClient and serverTunnel transportConnects then drops; certificate or key error
Private name lookupApps via the tunnelResolver inside the tunTunnel up, internal sites do not resolve

Tiga tahap, tiga gejala berbeda. Satu pesan kegagalan yang berbunyi «tidak dapat terhubung» meleburkan semuanya, itulah sebabnya orang akhirnya menyunting bidang server DNS untuk memperbaiki masalah yang terjadi sebelum bidang itu pernah dibaca.

Mengapa bootstrap bisa buntu

Always-on dengan pemblokiran aktif berarti lalu lintas yang tidak berada di dalam VPN dibuang, termasuk lalu lintas dari aplikasi pemilik VPN. Jalan keluarnya eksplisit: aplikasi memanggil protect() pada sebuah socket, yang mengikatnya ke jaringan yang mendasari sehingga ia melewati tunnel dan diizinkan keluar. Setiap klien VPN harus melakukannya untuk transport-nya sendiri, atau ia tidak akan pernah mencapai server.

Sekarang pertimbangkan penerapan di mana satu-satunya resolver yang mengetahui nama endpoint justru berada di dalam tunnel. Klien membutuhkan tunnel untuk meresolusi nama, dan nama untuk membangun tunnel. Itu ketergantungan melingkar yang nyata, dan tidak ada konfigurasi klien yang dapat menyelesaikannya. Itu kesalahan desain, bukan bug.

Waktu menyingkap ketergantungan yang sama dalam bentuk yang lebih ringan. Saat boot sebelum pembukaan kunci pertama, perangkat mungkin belum memiliki jaringan yang dapat dipakai; di captive portal, jaringan ada tetapi memblokir semua kecuali portal; saat peralihan Wi-Fi ke seluler, jaringan yang mendasari socket terlindungi berubah dan klien harus menyadarinya lalu meresolusi ulang. Masing-masing adalah peristiwa bootstrap, dan masing-masing layak diuji dengan sengaja daripada ditemukan pada pukul 3 pagi.

Mengapa menyematkan jawaban bukan solusi

Jalan pintas yang menggoda adalah meresolusi nama sekali lalu menempelkan alamat hasilnya ke bidang numerik, atau mengeraskannya di build khusus. Ia tampak berhasil, dan ia mengubah nama menjadi potret. Ketika operator memindahkan endpoint — migrasi, perubahan anycast, alamat regional baru — klien terus menghubungi yang lama dan tidak ada apa pun di antarmuka yang menjelaskan mengapa.

Catatan DNS membawa time to live justru agar jawabannya dapat berubah; caching didefinisikan menurut masa hidup itu, bukan selamanya. Menyematkan jawaban membuang mekanisme yang membuat nama lebih baik daripada alamat, sambil tetap menanggung biaya operasional karena telah memakai nama.

Penyematan juga cenderung berjalan bersama kebiasaan buruk kedua: melonggarkan pemeriksaan identitas karena koneksi kini gagal dengan cara berbeda. Verifikasi identitas server bukan bagian dari masalah bootstrap, dan melemahkannya menukar ketidaknyamanan DNS dengan risiko penyadapan.

Desain yang bertahan setelah boot ulang

Penataan yang tahan lama memang tidak menarik. Pakai klien yang mengimplementasikan socket terlindungi dengan benar dan meresolusi endpoint-nya pada jaringan yang mendasari, dan beri ia nama endpoint yang teresolusi secara publik, atau melalui resolver yang terjangkau sebelum tunnel. Biarkan pemblokiran tetap aktif; mematikannya secara menyeluruh agar DNS bekerja menghilangkan sifat yang menjadi alasan penerapan itu ada.

Di tempat endpoint harus tetap privat, sediakan jalur bootstrap eksplisit yang dapat dipakai platform — resolver yang terjangkau tanpa tunnel, atau koneksi manajemen yang dipelihara operator — dan jaga pengecualian itu tetap sempit serta dimiliki oleh kebijakan, bukan oleh tombol pengguna. Dokumentasi Android VpnService adalah rujukan tentang apa yang dijamin platform soal perlindungan dan siklus hidup, dan rujukan VpnService.Builder menegaskan bahwa bidang DNS menerima alamat numerik.

Lalu verifikasi ketiga tahap itu, secara berurutan, pada koneksi baru setelah boot ulang: nama endpoint teresolusi, tunnel terbentuk dan peer terautentikasi, dan nama privat teresolusi melalui resolver tunnel. Jika tahap pertama gagal, tidak ada tahap berikutnya yang dapat bekerja, dan perbaikannya berada di jalur bootstrap — tidak pernah di bidang resolver.

  • Resolusi endpoint terjadi di dalam aplikasi, di luar tunnel, pada socket terlindungi.
  • Bidang DNS di pembangun adalah untuk aplikasi di dalam tunnel, bukan untuk endpoint klien sendiri.
  • Resolver yang hanya terjangkau melalui tunnel adalah jalan buntu, bukan start yang lambat.
  • Uji endpoint, autentikasi, dan pencarian privat secara terpisah setelah boot ulang.

Artikel terkait