आपका टनल कंटेनर काम करता है, docker compose exec vpn curl -s https://ifconfig.me प्रदाता के पते के साथ जवाब देता है, और फिर भी आपके डेस्कटॉप का ब्राउज़र आपके ISP से ही बाहर जाता है। यह अंतर अपेक्षित है। VPN क्लाइंट चलाने वाला कंटेनर एक नेटवर्क नेमस्पेस, रूट और एक टनल इंटरफ़ेस रखता है, और ऐसा कुछ नहीं जो HTTP या SOCKS बोले; उस पर पोर्ट प्रकाशित करना ऐसा श्रोता नहीं बना सकता जो कभी था ही नहीं।

क्लाइंट कहाँ चलता है, यह डिज़ाइन तय करता है। पड़ोसी कंटेनर टनल के नेमस्पेस में जा सकता है, डेस्कटॉप ऐप नहीं जा सकता, और राउटर को प्रॉक्सी फ़ील्ड नहीं, रूट चाहिए। मैपिंग ग़लत हुई तो लक्षण वही रहेगा: कनेक्शन अस्वीकृत, या ट्रैफ़िक चुपचाप पुराने रास्ते से जाता हुआ।

व्यवस्था को उस जगह के अनुरूप बनाएँ जहाँ क्लाइंट चलता है

Compose संपादित करने से पहले एक सवाल पूछें: क्या क्लाइंट को VPN कंटेनर के नेटवर्क नेमस्पेस के अंदर शुरू किया जा सकता है? जो पहले से Linux कंटेनर के रूप में चलता है, वह कर सकता है। आपके डेस्क पर ब्राउज़र, IDE या CLI नहीं कर सकता, क्योंकि उसकी प्रॉक्सी सेटिंग प्रोटोकॉल सेवा की अपेक्षा करती है, नेमस्पेस की नहीं।

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

ये तीन आपस में नहीं मिलते। कंटेनर के ब्रिज पते की ओर इशारा करता HTTP प्रॉक्सी फ़ील्ड वहाँ प्रॉक्सी सुनता न हो तो कहीं नहीं पहुँचता, और प्रॉक्सी श्रोता राउटर का ट्रैफ़िक रूट नहीं करता। पहले तय करें, फिर मिलते हुए खंड का पालन करें।

टनल नेमस्पेस को पड़ोसी कंटेनर के साथ साझा करें

यह सबसे सस्ता विकल्प है क्योंकि इसमें कोई प्रॉक्सी प्रोटोकॉल शामिल नहीं है। ऐप vpn सेवा के नेमस्पेस में शामिल होता है और उसके इंटरफ़ेस, रूट और पोर्ट स्पेस विरासत में पाता है:

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

नेमस्पेस किसी दूसरी सेवा का होने से तीन सीमाएँ निकलती हैं। ऐप को अपनी networks कुंजी नहीं मिलती, क्योंकि जुड़ने के लिए उसके पास नेमस्पेस नहीं है। पोर्ट प्रकाशन vpn पर है, क्योंकि नेमस्पेस वहीं रहता है। और vpn को फिर से बनाने से वह नेमस्पेस नष्ट हो जाता है जिसमें ऐप जुड़ा था, इसलिए docker compose up -d --force-recreate vpn आपको app भी फिर से बनाने देता है; साधारण रीस्टार्ट हमेशा पर्याप्त नहीं होता। Compose सेवा संदर्भ इस व्यवस्था और इसकी पोर्ट प्रकाशन सीमा को समझाता है।

यह मत मानिए कि रिज़ॉल्वर साथ आता है। /etc/resolv.conf हर कंटेनर की फ़ाइल है, नेटवर्क नेमस्पेस का हिस्सा नहीं, इसलिए ऐप के पैकेट टनल से बाहर जाते समय भी वह होस्ट के रिज़ॉल्वर से पूछ सकता है। इसे कंटेनर के अंदर से पढ़ें और जब निजी नाम टनल से हल होने चाहिए तब ऐप पर dns: सेट करें।

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

अगर रूट सूची में टनल इंटरफ़ेस है और पता प्रदाता का है, तो ऐप टनल के अंदर है। अगर इंटरफ़ेस नहीं है, तो vpn के पास टनल होने से पहले app शुरू हो गया था, इसलिए vpn के स्वस्थ होने की सूचना देने पर app फिर से बनाएँ।

होस्ट क्लाइंट के लिए नेमस्पेस में असली प्रॉक्सी श्रोता रखें

डेस्कटॉप ब्राउज़र नेमस्पेस में शामिल नहीं हो सकता, इसलिए टनल को सेवा के रूप में खोलना पड़ेगा। vpn नेमस्पेस के अंदर असली SOCKS या HTTP प्रॉक्सी चलाएँ और केवल उसका पोर्ट प्रकाशित करें:

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

होस्ट की ओर का पता उस मैपिंग का महत्वपूर्ण आधा है। बाईं ओर का 127.0.0.1:1080 श्रोता को आपके LAN से बाहर रखता है; नंगा "1080:1080" आपकी मशीन तक पहुँच सकने वाले हर डिवाइस के लिए खुली प्रॉक्सी प्रकाशित करता है।

कंटेनर की ओर का अपना जाल है। प्रकाशित पोर्ट कंटेनर के ब्रिज पते पर पहुँचाए जाते हैं, उसके loopback पर नहीं, इसलिए नेमस्पेस के अंदर --socks 127.0.0.1:1080 से शुरू प्रॉक्सी पड़ोसियों के कनेक्शन स्वीकार करता है और प्रकाशित पोर्ट से आने वाला सब कुछ अस्वीकार करता है। इसे 0.0.0.0 से बाँधें और अलगाव के लिए होस्ट की ओर के loopback बंधन पर भरोसा करें। यही नियम प्रॉक्सी कॉन्फ़िग फ़ाइल के सुनने के पते पर भी लागू होता है।

फिर तय करें कि नाम कहाँ हल होंगे। curl में --socks5 होस्टनाम को स्थानीय रूप से हल करता है और --socks5-hostname नाम प्रॉक्सी को भेजता है; ब्राउज़र वही स्विच दूसरे लेबल के नीचे दिखाते हैं। स्थानीय समाधान पेज के टनल से लोड होने पर भी क्वेरी लीक कर देता है।

कंटेनर को गेटवे तभी मानें जब वापसी रूट हो

राउटर, VM और फ़ोन HTTP प्रॉक्सी फ़ील्ड इस्तेमाल नहीं करेंगे, और कुछ ऐप्लिकेशन प्रॉक्सी चरों को पूरी तरह नज़रअंदाज़ करते हैं। उनका ट्रैफ़िक रूट करने का मतलब लेयर 3 है: कंटेनर पैकेट आगे भेजता है और टनल इंटरफ़ेस पर पते अनुवाद करता है।

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

दो चीज़ें आसानी से छूट जाती हैं। क्लाइंट को ऐसा रूट चाहिए जो उसके डिफ़ॉल्ट गेटवे को इस होस्ट पर भेजे, और जवाबों को वापसी का रास्ता मिलना चाहिए, या तो ऊपरी राउटर पर स्थिर रूट से या क्लाइंट की ओर वाले इंटरफ़ेस पर NAT से। इनमें से एक भी न हो तो टनल अनुरोध बाहर ले जाता है और जवाब गायब हो जाता है।

इसका प्रभाव दायरा भी सबसे चौड़ा है। पूरे LAN के लिए गेटवे बना होस्ट हर ग़लत कॉन्फ़िगर क्लाइंट को आपके VPN खाते से भेजता है, और टनल गिरने पर kill switch के अनुसार या तो LAN अंधेरे में चला जाता है या ISP पर वापस गिर जाता है।

एग्ज़िट पथ जाँचें, फिर क्रम से पीछे हटें

इसी क्रम में जाँचें और पहली विफलता पर रुकें: नेमस्पेस के अंदर एग्ज़िट पता, होस्ट से प्रॉक्सी के ज़रिए एग्ज़िट पता, फिर निजी होस्ट के लिए नाम समाधान।

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

पहले दो पते प्रदाता से मेल खाने चाहिए, और तीसरा नाम-त्रुटि से विफल होने के बजाय प्रॉक्सी से हल होना चाहिए। पहली पंक्ति का मेल खाना और दूसरी का विफल होना बताता है कि श्रोता या प्रकाशित पोर्ट ग़लत है, टनल नहीं।

पीछे हटना सेटअप का उलटा है। प्रॉक्सी पर्यावरण चरों को shell प्रोफ़ाइल और किसी भी systemd यूनिट से हटाएँ, फिर स्टैक नीचे उतारें ताकि साझा नेमस्पेस अपने मालिक के साथ गायब हो जाए। प्रॉक्सी सेवा हटाने से पहले प्रकाशित पोर्ट हटाएँ, वरना होस्ट पर ऐसा loopback श्रोता रह जाता है जिसे कोई नहीं पढ़ता।

आगे बढ़ने से पहले चार बातें पक्की करें: जिस क्लाइंट की आपको चिंता है वह सचमुच टनल तक पहुँचता है, केवल नेमस्पेस का मालिक पोर्ट प्रकाशित करता है, निजी नाम वहीं हल होते हैं जहाँ आपने चाहा था, और loopback न हो ऐसे होस्ट पते पर कुछ नहीं सुनता। इनमें से हर एक उत्पादन में चुपचाप विफल होता है, और हर एक ऊपर की एक-पंक्ति जाँच है।

संबंधित लेख