Cara merutekan lalu lintas host melalui kontainer Docker VPN
Kontainer VPN adalah ruang nama jaringan, bukan proxy. Pilih netns bersama, pendengar SOCKS sungguhan, atau gateway terutekan, lalu verifikasi jalur keluar.
Kontainer terowongan Anda berfungsi, docker compose exec vpn curl -s https://ifconfig.me menjawab dengan alamat penyedia, dan browser di desktop Anda tetap keluar melalui ISP Anda. Celah itu wajar. Kontainer yang menjalankan klien VPN memegang ruang nama jaringan, rute, dan antarmuka terowongan, dan tidak ada yang berbicara HTTP atau SOCKS; menerbitkan port padanya tidak bisa menciptakan pendengar yang tidak pernah ada.
Di mana klien berjalan menentukan rancangan. Kontainer saudara dapat pindah ke ruang nama terowongan, aplikasi desktop tidak bisa, dan router butuh rute, bukan kolom proxy. Salah memetakan, gejalanya sama: koneksi ditolak, atau lalu lintas yang diam-diam menempuh jalur lama.
Sesuaikan tatanan dengan tempat klien berjalan
Ajukan satu pertanyaan sebelum menyunting Compose: dapatkah klien dijalankan di dalam ruang nama jaringan kontainer VPN? Apa pun yang sudah berjalan sebagai kontainer Linux bisa. Browser, IDE, atau CLI di meja Anda tidak bisa, karena setelan proxy-nya mengharapkan layanan protokol, bukan ruang nama.
| Client | Arrangement | What must already exist |
|---|---|---|
| Another Compose service | Shares the vpn namespace via network_mode: service:vpn | A working tunnel and correct start order |
| Host browser, IDE or CLI | Proxy listener inside the namespace, published to host loopback | A configured SOCKS or HTTP proxy and its access rules |
| Router, VM or phone | The container as a layer-3 gateway | Forwarding, NAT and a return route |
Ketiganya tidak bercampur. Kolom proxy HTTP yang diarahkan ke alamat jembatan kontainer tidak mencapai apa pun kecuali ada proxy yang mendengarkan di sana, dan pendengar proxy tidak merutekan lalu lintas router. Putuskan dulu, lalu ikuti bagian yang sesuai.
Bagikan ruang nama terowongan dengan kontainer saudara
Ini opsi termurah karena tidak ada protokol proxy yang terlibat. Aplikasi bergabung ke ruang nama layanan vpn dan mewarisi antarmuka, rute, serta ruang portnya:
services:
vpn:
image: your-vpn-client
cap_add:
- NET_ADMIN
healthcheck:
test: ["CMD-SHELL", "ip link show tun0 >/dev/null"]
interval: 10s
retries: 5
app:
image: your-app
network_mode: service:vpn
depends_on:
vpn:
condition: service_healthyTiga batasan menyusul dari kenyataan bahwa ruang nama milik layanan lain. Aplikasi tidak mendapat kunci networks sendiri, karena tidak punya ruang nama untuk ditempeli. Penerbitan port ada pada vpn, sebab di sanalah ruang nama itu tinggal. Dan membuat ulang vpn menghancurkan ruang nama yang dimasuki aplikasi, jadi docker compose up -d --force-recreate vpn membiarkan Anda membuat ulang app juga; mulai ulang biasa tidak selalu cukup. Referensi layanan Compose membahas tatanan ini dan batasan penerbitan portnya.
Jangan anggap resolver ikut serta. /etc/resolv.conf adalah berkas per kontainer, bukan bagian dari ruang nama jaringan, jadi aplikasi masih dapat menanyai resolver host sementara paketnya keluar melalui terowongan. Bacalah dari dalam kontainer dan setel dns: pada aplikasi bila nama privat harus diselesaikan melalui terowongan.
docker compose exec app ip route
docker compose exec app cat /etc/resolv.conf
docker compose exec app curl -s https://ifconfig.meJika daftar rute memuat antarmuka terowongan dan alamatnya milik penyedia, aplikasi ada di dalam terowongan. Jika antarmukanya tidak ada, app mulai sebelum vpn punya terowongan, jadi buat ulang app begitu vpn melaporkan sehat.
Tempatkan pendengar proxy sungguhan di ruang nama untuk klien host
Browser desktop tidak dapat bergabung ke ruang nama, jadi terowongan harus diekspos sebagai layanan. Jalankan proxy SOCKS atau HTTP sungguhan di dalam ruang nama vpn dan terbitkan hanya portnya:
services:
vpn:
ports:
- "127.0.0.1:1080:1080"
proxy:
image: your-proxy
network_mode: service:vpn
command: ["--socks", "0.0.0.0:1080"]Alamat sisi host adalah separuh penting dari pemetaan itu. 127.0.0.1:1080 di kiri menjaga pendengar di luar LAN Anda; "1080:1080" telanjang menerbitkan proxy terbuka ke setiap perangkat yang dapat menjangkau mesin Anda.
Sisi kontainer punya jebakannya sendiri. Port yang diterbitkan dikirim ke alamat kontainer di jembatan, bukan ke loopback-nya, jadi proxy yang dijalankan dengan --socks 127.0.0.1:1080 di dalam ruang nama menerima koneksi dari saudara dan menolak semua yang datang melalui port terbitan. Ikat ke 0.0.0.0 dan andalkan ikatan loopback sisi host untuk isolasi. Aturan yang sama berlaku untuk alamat dengar di berkas konfigurasi proxy.
Lalu putuskan di mana nama diselesaikan. Di curl, --socks5 menyelesaikan nama host secara lokal dan --socks5-hostname mengirim nama ke proxy; browser menampilkan sakelar yang sama dengan label berbeda. Resolusi lokal membocorkan kueri bahkan saat halaman dimuat melalui terowongan.
Perlakukan kontainer sebagai gateway hanya dengan rute balik
Router, VM, dan ponsel tidak akan memakai kolom proxy HTTP, dan sebagian aplikasi mengabaikan variabel proxy sepenuhnya. Merutekan lalu lintasnya berarti lapisan 3: kontainer meneruskan paket dan menerjemahkan alamat pada antarmuka terowongan.
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADEDua hal mudah terlewat. Klien butuh rute yang mengarahkan gateway bawaannya ke host ini, dan balasan harus menemukan jalan pulang, entah lewat rute statis di router hulu atau lewat NAT pada antarmuka yang menghadap klien. Tanpa salah satunya, terowongan membawa permintaan keluar dan balasannya menghilang.
Dampaknya juga paling luas. Host yang menjadi gateway bagi seluruh LAN mengirim setiap klien yang salah konfigurasi melalui akun VPN Anda, dan terowongan yang putus entah membutakan LAN atau kembali ke ISP tergantung kill switch.
Verifikasi jalur keluar, lalu gulung balik berurutan
Periksa dalam urutan ini dan berhenti pada kegagalan pertama: alamat keluar di dalam ruang nama, alamat keluar dari host melalui proxy, lalu resolusi nama untuk host privat.
docker compose exec vpn curl -s https://ifconfig.me
curl -s -x socks5h://127.0.0.1:1080 https://ifconfig.me
curl -s -x socks5h://127.0.0.1:1080 http://internal.example/healthDua alamat pertama harus cocok dengan penyedia, dan yang ketiga harus diselesaikan melalui proxy alih-alih gagal dengan galat nama. Baris pertama cocok dan baris kedua gagal berarti pendengar atau port terbitan yang salah, bukan terowongannya.
Menggulung balik adalah kebalikan dari penyiapan. Hapus variabel lingkungan proxy dari profil shell dan dari unit systemd mana pun, lalu turunkan tumpukan agar ruang nama bersama lenyap bersama pemiliknya. Hapus port terbitan sebelum menghapus layanan proxy, atau host menyimpan pendengar loopback yang tidak dibaca siapa pun.
Sebelum melanjutkan, pastikan empat hal: klien yang Anda pedulikan benar-benar mencapai terowongan, hanya pemilik ruang nama yang menerbitkan port, nama privat diselesaikan di tempat yang Anda maksud, dan tidak ada yang mendengarkan di alamat host yang bukan loopback. Semuanya gagal diam-diam di produksi, dan semuanya adalah pemeriksaan satu baris di atas.