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.

ClientArrangementWhat must already exist
Another Compose serviceShares the vpn namespace via network_mode: service:vpnA working tunnel and correct start order
Host browser, IDE or CLIProxy listener inside the namespace, published to host loopbackA configured SOCKS or HTTP proxy and its access rules
Router, VM or phoneThe container as a layer-3 gatewayForwarding, 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_healthy

Tiga 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.me

Jika 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 MASQUERADE

Dua 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/health

Dua 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.

Artikel terkait