OpenVPN lewat SOCKS5: samakan versi, transport, dan DNS
Rantai SOCKS gagal ketika versi proxy, transport, atau jalur DNS tidak cocok. Pilih SOCKS5, bawa TCP, dan jaga rantai tetap di dalam namespace.
Salah satu jalur keluar dari workstation ini adalah proxy SOCKS, dan OpenVPN di belakangnya melaporkan timeout koneksi tanpa keterangan yang berguna. Browser di mesin yang sama berfungsi melalui proxy itu, kredensialnya benar, dan portnya menjawab. Tiga hal cukup sering berbeda untuk diperiksa lebih dulu: versi SOCKS yang dipakai proxy, transport yang dipilih klien, dan di mana resolusi nama terjadi. Pastikan masing-masing sebelum menyimpulkan bahwa firewall yang bersalah.
Samakan versi SOCKS sebelum menyalahkan firewall
OpenVPN komunitas berbicara SOCKS5 untuk socks-proxy. Arahkan ke proxy yang hanya menawarkan SOCKS4, koneksi TCP terbuka lalu macet, karena klien menunggu balasan atas sapaan yang tidak pernah diurai ujung lain. Dari luar, kemacetan itu terlihat persis seperti port tersaring, itulah sebabnya pertanyaan versi datang sebelum aturan firewall apa pun. Permintaan yang sadar SOCKS menyelesaikannya dalam satu perintah.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
Permintaan yang selesai membuktikan dua hal sekaligus: proxy menerima permintaan SOCKS dan proxy berhasil me-resolve nama. Tidak perlu skema URL, karena curl memperlakukan host telanjang sebagai HTTP, cukup untuk uji ini.
Permintaan itu juga menyingkirkan kegagalan yang disembunyikan log klien. Proxy bisa mengizinkan browser tetapi tetap menolak tujuan VPN, dan dalam kasus itu penolakan terjadi di CONNECT, sebelum autentikasi VPN apa pun. OpenVPN hanya melaporkan timeout, jadi jawaban proxy sendiri adalah bukti yang Anda butuhkan.
Transport harus TCP di kedua sisi
SOCKS5 membawa aliran TCP di sini, jadi terowongannya sendiri membutuhkan proto tcp-client. Profil yang masih disetel ke UDP tidak akan bekerja melalui jalur ini, karena klien tidak memakai mode asosiasi UDP protokol tersebut. Mengubah profil adalah perubahan nyata, bukan formalitas: ujung jauh harus mendengarkan TCP di port yang sama. Payload lalu menjadi TCP di dalam TCP, tempat segmen yang hilang dikirim ulang dua kali dan laju menurun, sesuatu yang sesi interaktif jauh lebih terasa daripada transfer besar.
proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050
Direktif ini menerima host proxy, port opsional, dan berkas kredensial opsional. Letakkan semuanya di dalam profil agar salinannya berperilaku sama di tempat lain.
Batasi seluruh rantai dalam satu kontainer
Melakukan rantai di host berarti mengambil alih rute bawaannya dan meninggalkan resolver dalam keadaan yang tak bisa dijelaskan kemudian. Namespace atau kontainer membatasinya, sehingga host tetap punya jalurnya sendiri sementara lompatan SOCKS dan terowongan hidup bersama. Di dalamnya tidak ada yang menyala tanpa perangkat terowongan, hak untuk mengonfigurasi perangkat itu, dan proxy yang bisa dijangkau. Layanan Compose mendapatkannya dengan cap_add: NET_ADMIN dan /dev/net/tun yang di-bind-mount.
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
Pasangan itu lebih sempit daripada menjalankan kontainer dengan hak istimewa, dan itulah seluruh akses perangkat yang dibutuhkan. Klien Tor atau kontainer proxy terpisah dapat menyediakan pendengarnya. Dalam kedua kasus, ikat ke loopback dan jangkau dari namespace melalui host alih-alih mengekspos proxy ke jaringan.
Resolusi nama adalah tempat isolasi gagal
Terowongan yang membawa paket tetapi bertanya ke resolver host tidak mengisolasi apa pun. Dua hal membuat isolasi nyata: namespace punya resolver sendiri, dan kuerinya melewati proxy atau terowongan, tidak pernah lewat antarmuka fisik. Gunakan dua nama untuk uji: satu yang hanya ada di balik terowongan, dan satu publik yang seharusnya mengikuti jalur yang sama.
docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example
Jika nama sisi jauh ter-resolve dan yang publik tidak, rantainya selektif, bukan rusak, dan selisihnya memberi tahu Anda jalur mana yang diambil tiap kueri. Jika keduanya ter-resolve dari host tetapi tidak satu pun di dalam kontainer, kontainer masih meminjam resolver host. Catat berkas resolver yang Anda temukan, karena itulah pengaturan yang harus diubah.
Buktikan setiap lompatan secara berurutan
Daftarnya pendek. Permintaan SOCKS5 mendapat jawaban, terowongan mencapai pendengarnya melalui proxy, dan paket yang meninggalkan namespace membawa alamat yang diharapkan sisi jauh. Pastikan satu per satu alih-alih menumpuk konfigurasi. Ketika klien menyatakan terhubung dan tidak ada yang bergerak, putusnya hampir selalu ada pada fakta kedua atau ketiga.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
docker compose exec vpn ip route get 203.0.113.10
docker compose exec vpn getent hosts internal.lab.example
Catat kombinasi yang berhasil: versi SOCKS, transport, resolver, dan pengaturan namespace. Menyelesaikan rantai ini kedua kali dari ingatan lebih mahal daripada catatannya. Simpan keempat fakta itu di tiket, bukan di utas obrolan.
Rantai yang melaporkan terhubung dan tidak melewatkan apa pun biasanya gagal pada lompatan yang belum Anda buktikan. Uji lompatan itu sebelum menambah lapisan lain.