VPN क्लाइंट को कंटेनर में रखें और आपको अंदर टनल वाला एक नेमस्पेस मिलता है, ऐसा होस्ट नहीं जो अपना सारा ट्रैफ़िक VPN से रूट करे। ये अलग परियोजनाएँ हैं, और इन्हें एक मानना ही वह तरीका है जिससे कंटेनर गलती से विशेषाधिकार प्राप्त हो जाते हैं। यह गाइड केवल पहले को कवर करता है: एक समीक्षित इमेज, एक संरक्षित प्रोफ़ाइल और अपने ही नेटवर्क नेमस्पेस तक सीमित क्लाइंट प्रक्रिया।

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

कंटेनर को क्या मिलता है और क्या नहीं

प्रोफ़ाइल और वह जिसका भी संदर्भ देती है, उसे सीमित अनुमतियों वाली स्थानीय निर्देशिका में रखें, केवल-पढ़ने के लिए माउंट किया हुआ। प्रोफ़ाइल के अंदर के सापेक्ष पथ उसी माउंट के भीतर हल होने चाहिए; यह वह बारीकी है जो लोग चूक जाते हैं जब प्रमाणपत्र प्रोफ़ाइल से एक निर्देशिका ऊपर होता है और कंटेनर उसे कभी नहीं देखता।

services:
  vpn:
    image: ${VPN_CLIENT_IMAGE:?set the reviewed image reference}
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    volumes:
      - ./vpn:/vpn:ro
    working_dir: /vpn
    entrypoint: ["openvpn"]
    command: ["--config", "/vpn/client.ovpn"]

वह फ़ाइल तीन चीज़ें देती है और और कुछ नहीं माँगती। अगर आपकी परिनियोजन नीति कहती है तो इमेज संदर्भ को डाइजेस्ट से पिन किया जाना चाहिए, और प्रोफ़ाइल समीक्षित ही होनी चाहिए, होस्ट पर किसी द्वारा जगह पर संपादित की गई प्रति नहीं।

यहाँ केवल-पढ़ने का मतलब है कि कंटेनर आपकी होस्ट फ़ाइलें बदल नहीं सकता; इसका मतलब यह नहीं कि कंटेनर आपके द्वारा माउंट की गई निजी कुंजी पढ़ नहीं सकता। माउंट का पूरा उद्देश्य यही है, और इसीलिए फ़ाइल अनुमतियाँ, स्वामित्व और रहस्य होस्ट पर कैसे पहुँचा, अब भी मायने रखते हैं। कभी कमांड लाइन पर पासवर्ड न दें और न ही उसे इमेज परत में बेक करें, क्योंकि दोनों ऐसी जगहों पर बचे रहते हैं जिन्हें आप बाद में साफ़ नहीं कर सकते।

क्षमताएँ, entrypoint और उनके बीच का जाल

दो सेटिंग्स ज़रूरी हैं और वे असंबंधित काम करती हैं। NET_ADMIN कंटेनर के नेमस्पेस में इंटरफ़ेस और रूट के हेरफेर की अनुमति देता है। /dev/net/tun डिवाइस प्रविष्टि प्रक्रिया को टनल डिवाइस खोलने ही की अनुमति देती है। एक को दूसरे के बिना देना स्पष्ट विफलता पैदा करता है, जो सुविधाजनक है: अनुपस्थित TUN डिवाइस खोलते समय विफल होता है, जबकि अनुपस्थित क्षमता तब विफल होती है जब क्लाइंट इंटरफ़ेस कॉन्फ़िगर करने की कोशिश करता है।

इनमें से कोई भी privileged: true को न्यायसंगत नहीं ठहराता। विशेषाधिकार प्राप्त कंटेनर को हर क्षमता और डिवाइस पहुँच मिलती है, और यह इस कार्यभार की ज़रूरत से कहीं बड़ा अनुदान है। रनटाइम विशेषाधिकार और क्षमता संदर्भ बताता है कि यह अनुदान कितनी दूर तक पहुँचता है। अगर कोई chart या ब्लॉग पोस्ट इसे माँगता है, तो पहले जाँचें कि आवश्यकता वास्तव में अनुपस्थित डिवाइस पथ थी या अनुपस्थित क्षमता।

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

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

नेमस्पेस के अंदर से जाँचें, होस्ट से नहीं

स्टैक ऊपर लाएँ, लॉग में पुष्टि करें कि क्लाइंट जुड़ी अवस्था तक पहुँचा, और फिर उस नेमस्पेस का निरीक्षण करें जो वास्तव में टनल रखता है।

docker compose up -d
docker compose logs --tail 40 vpn
docker compose exec vpn ip -br addr
docker compose exec vpn ip route

पता सूची में पूल से पता वाला टनल इंटरफ़ेस दिखना चाहिए, और रूट तालिका में उसकी ओर इशारा करते पुश किए गए गंतव्य दिखने चाहिए। अगर इंटरफ़ेस नहीं है, तो क्लाइंट उसे बनाने के बिंदु तक कभी नहीं पहुँचा। अगर वह है पर कोई रूट उसका उपयोग नहीं करता, तो खोजने की जगह push या रूट विकल्प हैं।

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

डिस्कनेक्टेड अवस्था अनुबंध का हिस्सा है

पुनःकनेक्ट व्यवहार को अपनी जाँच चाहिए, क्योंकि पुनःआरंभ नीति साबित करती है कि प्रक्रिया फिर से शुरू होती है और इस बीच ट्रैफ़िक क्या करता है, इस पर कुछ नहीं कहती। टनल रोकें, इच्छित गंतव्य आज़माएँ और देखें कि कनेक्शन अस्वीकार होता है, अटक जाता है, या कंटेनर के सामान्य रूट से चुपचाप सफल होता है। अंतिम परिणाम ही मायने रखता है, और वह स्वस्थ लॉग में अदृश्य है।

अगर कार्यभार को कभी सामान्य मार्ग का उपयोग नहीं करना चाहिए, तो उसे फ़ायरवॉल नियमों और नेमस्पेस के अंदर तैयारी संकेत के साथ स्पष्ट रूप से डिज़ाइन करें। Kill switch वह नीति है जिसे आप लिखते और जाँचते हैं, कंटेनर में क्लाइंट चलाकर मिलने वाला गुण नहीं।

अंत में, सीमा याद रखें: ये रूट कंटेनर के नेमस्पेस में रहते हैं और होस्ट की रूटिंग तालिका की जगह नहीं लेते। Docker के फ़ॉरवर्डिंग, अनुवाद और फ़ायरवॉल नियम बाहरी मार्ग का हिस्सा बने रहते हैं, और प्रकाशित पोर्ट VPN इंटरफ़ेस नहीं है।

संबंधित लेख