Tünel konteyneriniz çalışıyor, docker compose exec vpn curl -s https://ifconfig.me sağlayıcının adresiyle yanıt veriyor, yine de masaüstünüzdeki tarayıcı ISP'niz üzerinden çıkıyor. Bu boşluk beklenen bir durum. Bir VPN istemcisi çalıştıran konteyner bir ağ ad alanı, yollar ve bir tünel arayüzü tutar, HTTP veya SOCKS konuşan hiçbir şey tutmaz; üzerinde port yayınlamak hiç var olmamış bir dinleyici yaratamaz.

İstemcinin nerede çalıştığı tasarımı belirler. Kardeş bir konteyner tünelin ad alanına geçebilir, masaüstü uygulaması geçemez ve yönlendiricinin proxy alanına değil yollara ihtiyacı vardır. Eşlemeyi yanlış yaparsanız belirti aynıdır: bağlantı reddedildi veya sessizce eski yolu izleyen trafik.

Düzeni istemcinin çalıştığı yere uyarlayın

Compose'u düzenlemeden önce bir soru sorun: istemci VPN konteynerinin ağ ad alanının içinde başlatılabilir mi? Zaten bir Linux konteyneri olarak çalışan her şey başlatılabilir. Masanızdaki tarayıcı, IDE veya CLI başlatılamaz, çünkü proxy ayarı bir protokol hizmeti bekler, ad alanı değil.

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

Bu üçü karışmaz. Konteynerin köprü adresine yönelen bir HTTP proxy alanı, orada bir proxy dinlemiyorsa hiçbir yere ulaşmaz ve bir proxy dinleyicisi yönlendiricinin trafiğini yönlendirmez. Önce karar verin, sonra ilgili bölümü izleyin.

Tünel ad alanını kardeş bir konteynerle paylaşın

Bu en ucuz seçenektir çünkü hiçbir proxy protokolü işin içinde değildir. Uygulama vpn hizmetinin ad alanına girer ve arayüzlerini, yollarını ve port uzayını devralır:

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

Ad alanının başka bir hizmete ait olmasından üç kısıt doğar. Uygulama kendi networks anahtarını almaz, çünkü bağlanacağı bir ad alanı yoktur. Port yayınlama vpn'e aittir, çünkü ad alanı orada yaşar. Ve vpn'i yeniden oluşturmak uygulamanın girdiği ad alanını yok eder, bu yüzden docker compose up -d --force-recreate vpn app'i de yeniden oluşturmayı size bırakır; basit bir yeniden başlatma her zaman yeterli değildir. Compose hizmet başvurusu bu düzeni ve port yayınlama kısıtını kapsar.

Çözümleyicinin birlikte geldiğini varsaymayın. /etc/resolv.conf konteyner başına bir dosyadır, ağ ad alanının parçası değildir, bu yüzden uygulama paketleri tünelden çıkarken hâlâ ana makinenin çözümleyicisine sorabilir. Onu konteynerin içinden okuyun ve özel adların tünel üzerinden çözülmesi gerektiğinde uygulamada dns: ayarlayın.

docker compose exec app ip route
docker compose exec app cat /etc/resolv.conf
docker compose exec app curl -s https://ifconfig.me

Yol listesi tünel arayüzünü içeriyorsa ve adres sağlayıcınınsa, uygulama tünelin içindedir. Arayüz yoksa app, vpn'in tüneli olmadan önce başlamıştır, bu yüzden vpn sağlıklı bildirdiğinde app'i yeniden oluşturun.

Ana makine istemcileri için ad alanına gerçek bir proxy dinleyicisi koyun

Masaüstü tarayıcısı bir ad alanına katılamaz, bu yüzden tünel bir hizmet olarak açılmalıdır. vpn ad alanının içinde gerçek bir SOCKS veya HTTP proxy çalıştırın ve yalnızca portunu yayınlayın:

services:
  vpn:
    ports:
      - "127.0.0.1:1080:1080"
  proxy:
    image: your-proxy
    network_mode: service:vpn
    command: ["--socks", "0.0.0.0:1080"]

Ana makine tarafındaki adres bu eşlemenin önemli yarısıdır. Soldaki 127.0.0.1:1080 dinleyiciyi LAN'ınızın dışında tutar; çıplak "1080:1080" makinenize ulaşabilen her cihaza açık bir proxy yayınlar.

Konteyner tarafının kendi tuzağı vardır. Yayınlanan portlar konteynerin köprüdeki adresine teslim edilir, loopback'ine değil, bu yüzden ad alanının içinde --socks 127.0.0.1:1080 ile başlatılan bir proxy kardeşlerden gelen bağlantıları kabul eder ve yayınlanan porttan gelen her şeyi reddeder. Onu 0.0.0.0 adresine bağlayın ve yalıtım için ana makine tarafındaki loopback bağlamasına güvenin. Aynı kural bir proxy yapılandırma dosyasındaki dinleme adresi için de geçerlidir.

Sonra adların nerede çözüleceğine karar verin. curl'de --socks5 ana makine adını yerel olarak çözer ve --socks5-hostname adı proxy'ye gönderir; tarayıcılar aynı anahtarı başka bir etiket altında sunar. Yerel çözümleme, sayfa tünelden yüklense bile sorguyu sızdırır.

Konteyneri yalnızca dönüş yolu varsa ağ geçidi olarak görün

Yönlendiriciler, VM'ler ve telefonlar bir HTTP proxy alanı kullanmayacak ve bazı uygulamalar proxy değişkenlerini tamamen yok sayar. Trafiklerini yönlendirmek katman 3 anlamına gelir: konteyner paketleri iletir ve tünel arayüzünde adresleri çevirir.

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

İki şey kolayca gözden kaçar. İstemcinin varsayılan ağ geçidini bu ana makineye yönlendiren bir yola ihtiyacı vardır ve yanıtlar geri dönüş yolunu bulmalıdır; ya üst yönlendiricide statik bir yol ile ya da istemcilere bakan arayüzde NAT ile. Bunlardan biri olmadan tünel isteği dışarı taşır ve yanıt kaybolur.

Ayrıca en geniş etki alanına sahiptir. Tüm LAN için ağ geçidi olarak hizmet eden bir ana makine, yanlış yapılandırılmış her istemciyi VPN hesabınızdan geçirir ve tünel düşerse kill switch'e bağlı olarak LAN karanlığa gömülür veya ISP'ye geri döner.

Çıkış yolunu doğrulayın, sonra sırayla geri alın

Bu sırayla kontrol edin ve ilk hatada durun: ad alanı içindeki çıkış adresi, ana makineden proxy üzerinden çıkış adresi, sonra özel bir ana makine için ad çözümlemesi.

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

İlk iki adres sağlayıcıyla eşleşmelidir ve üçüncüsü ad hatasıyla başarısız olmak yerine proxy üzerinden çözülmelidir. İlk satırın eşleşip ikincinin başarısız olması, dinleyicinin veya yayınlanan portun yanlış olduğu anlamına gelir, tünelin değil.

Geri alma, kurulumun tersidir. Proxy ortam değişkenlerini kabuk profilinden ve herhangi bir systemd biriminden kaldırın, sonra paylaşılan ad alanı sahibiyle birlikte yok olsun diye yığını indirin. Yayınlanan portu proxy hizmetini silmeden önce silin, aksi halde ana makinede kimsenin okumadığı bir loopback dinleyicisi kalır.

Devam etmeden önce dört şeyi doğrulayın: önemsediğiniz istemci gerçekten tünele ulaşıyor, portları yalnızca ad alanının sahibi yayınlıyor, özel adlar amaçladığınız yerde çözülüyor ve loopback olmayan bir ana makine adresinde hiçbir şey dinlemiyor. Bunların her biri üretimde sessizce başarısız olur ve her biri yukarıdaki tek satırlık bir kontroldür.

İlgili makaleler