Docker कंटेनर VPN के पीछे के होस्ट तक क्यों नहीं पहुँचता
ब्रिज कंटेनरों का अपना नेमस्पेस होता है, इसलिए होस्ट की टनल उन्हें अदृश्य रहती है। DNS बदलने से पहले होस्ट नेटवर्किंग, tun डिवाइस और macvlan की तुलना करें।
कॉर्पोरेट VPN के पीछे किसी भी चीज़ तक न पहुँचने वाला कंटेनर आमतौर पर टनल से भिन्न नेटवर्क नेमस्पेस में रहता है। होस्ट क्लाइंट के रूट, DNS सर्वर और फ़ायरवॉल मार्क होस्ट के स्टैक के हैं; ब्रिज-नेटवर्क कंटेनर का अपना स्टैक होता है। यही एक तथ्य प्लेटफ़ॉर्म टीम तक पहुँचने वाली अधिकांश रिपोर्टों को समझाता है, और यही कारण है कि «VPN टूटा हुआ है» और «Docker VPN को बायपास करता है» दोनों एक ही समय में ग़लत हो सकते हैं। एक लक्षण के पीछे दो बिल्कुल अलग सेटअप छिपे हैं, इसलिए कोई भी सेटिंग बदलने से पहले तय करें कि आपके पास कौन-सा है।
पता लगाएँ कि टनल किसके नेमस्पेस का है
macOS या Windows के लिए Docker Desktop पर कंटेनर Linux वर्चुअल मशीन के भीतर चलते हैं। डेस्कटॉप पर इंस्टॉल किया गया VPN क्लाइंट डेस्कटॉप ऑपरेटिंग सिस्टम में टनल बनाता है, और वर्चुअल मशीन उसे कभी नहीं देखती। कोई भी कंटेनर कॉन्फ़िगरेशन इसे ठीक नहीं करता, क्योंकि कंटेनर को जिस इंटरफ़ेस की ज़रूरत होगी वह उसके नेटवर्क नेमस्पेस में है ही नहीं।
Linux होस्ट पर टनल होस्ट नेमस्पेस में रहती है, और ब्रिज कंटेनर आमतौर पर होस्ट की रूटिंग टेबल के ज़रिए बाहर जाते समय स्रोत NAT लागू करके उस तक पहुँचते हैं। जब वह रास्ता विफल होता है, तो कारण आमतौर पर फ़ॉरवर्डिंग नीति, रिवर्स-पाथ फ़िल्टरिंग या अतिव्यापी सबनेट होता है, न कि ग़ायब रूट। आगे पढ़ने से पहले पुष्टि करें कि आप दोनों में से किस दुनिया में हैं:
docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5
उन दो रूटिंग टेबलों के बीच का अंतर ही एक स्क्रीन पर पूरी समस्या है। यदि होस्ट के दृश्य में टनल इंटरफ़ेस है और ब्रिज के दृश्य में नहीं, तो आप नेमस्पेस अलगाव देख रहे हैं, और बाकी सब कुछ उसे कैसे पार करना है इसका चुनाव है।
होस्ट नेटवर्किंग एक परीक्षण है, डिज़ाइन नहीं
कंटेनर को होस्ट नेटवर्किंग के साथ चलाना, जिसे Docker होस्ट नेटवर्क नेमस्पेस साझा करने के रूप में दस्तावेज़ित करता है, उसे टनल इंटरफ़ेस और उसके रूट सीधे विरासत में देता है। यदि वही अनुरोध फिर सफल होता है, तो रूट सिद्धांत पुष्ट हो जाता है और विफलता नेमस्पेस अलगाव है, न कि क्रेडेंशियल, DNS या कोई एक्सेस नियम।
docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health
इसे निदान के रूप में रखें। होस्ट नेटवर्किंग पोर्ट प्रकाशन और कंटेनर से आप जो अलगाव चाहते थे उसका अधिकांश हिस्सा छोड़ देती है, और Docker Desktop पर «host» का अर्थ वर्चुअल मशीन है, डेस्कटॉप नहीं, इसलिए वहाँ की सफलता या विफलता आपको भ्रमित कर सकती है यदि आप भूल जाएँ कि किस होस्ट को संबोधित कर रहे थे।
tun डिवाइस और उसके साथ आने वाले विशेषाधिकार
कंटेनर के भीतर के VPN क्लाइंट को टनल डिवाइस और उसे कॉन्फ़िगर करने की अनुमति चाहिए। आम शॉर्टकट --privileged है, जो हर डिवाइस देता है और पूरे कंटेनर में सुरक्षा नीति ढीली करता है। यह इस काम की ज़रूरत से कहीं अधिक है, और समीक्षा में इसे उचित ठहराना कठिन है।
sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client
संकरा रूप एक ही डिवाइस नोड को मैप करता है और केवल नेटवर्क प्रशासन क्षमता जोड़ता है। पहले होस्ट पर मॉड्यूल लोड करें ताकि नोड मौजूद रहे। यदि कंटेनर शुरू होता है और क्लाइंट बताता है कि वह टनल डिवाइस नहीं खोल सकता, तो प्रोफ़ाइल पर संदेह करने से पहले मैपिंग जाँचें, क्योंकि वह त्रुटि आमतौर पर शाब्दिक होती है।
इस डिज़ाइन का अर्थ यह भी है कि क्लाइंट प्रति कंटेनर चलता है। यह सही उत्तर है जब हर वर्कलोड को अपनी टनल चाहिए, और ग़लत उत्तर तब जब आप केवल होस्ट की टनल दृश्यमान चाहते थे, जो प्लेटफ़ॉर्म टीम ने शायद मान लिया था कि आप कर रहे हैं।
ब्रिज NAT उस स्रोत को बदलता है जो VPN देखता है
डिफ़ॉल्ट ब्रिज के साथ कंटेनर का बाहर जाने वाला ट्रैफ़िक होस्ट के पते में अनूदित होता है। इसलिए VPN के पीछे कॉर्पोरेट पक्ष कंटेनर का नहीं, होस्ट का टनल पता देखता है, स्रोत-आधारित एक्सेस नियम ऐसे व्यवहार करते हैं जैसे अनुरोध होस्ट ने भेजा हो, और दो कंटेनर VPN सर्वर के लिए अविभेद्य हो जाते हैं।
macvlan या ipvlan इसके बजाय कंटेनर को LAN पता देता है, जो LAN खोज में मदद करता है और कंटेनर को सेगमेंट पर समकक्ष जैसा दिखाता है। यह होस्ट की टनल को पूरी तरह बायपास भी करता है, इसलिए ऐसा कंटेनर केवल-VPN प्रीफ़िक्स तक नहीं पहुँचेगा जब तक VPN उस LAN से भी सुलभ न हो।
दोनों रूप वैध हैं; वे अलग-अलग आवश्यकताओं का उत्तर देते हैं। यदि आवश्यकता है «इस कंटेनर को केवल-VPN सेवा तक पहुँचना चाहिए», तो आप होस्ट के ज़रिए रूटिंग और कंटेनर के भीतर टनल समाप्त करने के बीच चुन रहे हैं। यह चुनाव तैनाती से पहले लिखें, पहले असफल अनुरोध के बाद नहीं। आप जो भी चुनें, दूर के सिरे को दिखने वाला स्रोत पता दर्ज करें, क्योंकि उसके एक्सेस नियम और उसके लॉग यही दिखाएँगे। जो डिज़ाइन वह पता नहीं बता सकता वह पूरा नहीं है।
DNS डिमन का अनुसरण करता है, टनल का नहीं
कंटेनर शुरू होते समय अपना रिज़ॉल्वर कॉन्फ़िगरेशन पाता है, जो डिमन या इमेज से नक़ल किया गया होता है। VPN के जुड़ने के बाद भेजे गए पते उस नक़ल के लिए बहुत देर से आते हैं, और वे कंटेनर में नहीं, होस्ट के रिज़ॉल्वर में भेजे जाते हैं।
सेवा के लिए रिज़ॉल्वर स्पष्ट रूप से सेट करें, या उसे टनल के ज़रिए सुलभ आंतरिक रिज़ॉल्वर की ओर इंगित करें। जो कंटेनर निजी नाम को सार्वजनिक पते में हल करता है वह आमतौर पर सार्वजनिक रिज़ॉल्वर का उपयोग करता है, टूटे रूट से नहीं पीड़ित होता, और सुधार compose फ़ाइल या डिमन कॉन्फ़िगरेशन में है।
यही तर्क बाहर जाने के पते के प्रश्न पर लागू होता है। यदि हर कंटेनर को अलग VPN पते से दिखना चाहिए, तो एक होस्ट टनल यह नहीं दे सकती क्योंकि NAT उन्हें एक स्रोत में समेट देता है। व्यवहार्य रूप हैं हर कंटेनर के नेमस्पेस में एक क्लाइंट या वह साइडकार जो टनल का मालिक है और अपना स्टैक साझा करता है, और दोनों यह बदल देते हैं कि एप्लिकेशन को कैसे संबोधित किया जाता है।
टिकट बंद करने से पहले चेकलिस्ट: टनल का मालिक नेमस्पेस पहचानें, होस्ट नेटवर्किंग से रास्ता साबित करें, केवल ज़रूरी tun डिवाइस मैप करें, NAT के बाद स्रोत पता याद रखें, रिज़ॉल्वर स्पष्ट सेट करें और प्रति-कंटेनर बाहर जाने वाले पतों को फ़्लैग नहीं, आर्किटेक्चर निर्णय मानें।