आपको कौन-सा क्रेडेंशियल स्रोत इस्तेमाल करना चाहिए, यह तीन बातें तय करती हैं: कंसोल पर कोई व्यक्ति बैठा है या नहीं, रहस्य डिस्क पर रह सकता है या नहीं, और क्या कोई दूसरी प्रक्रिया प्रॉम्प्ट का उत्तर देगी। ग़लत चुनाव करने पर क्लाइंट stdin की समस्या बताता है जबकि पासवर्ड पूरी तरह मान्य होता है, और यह ज़्यादातर लोगों को बिना कारण सर्वर तक भेज देता है। पहले रास्ता चुनें; त्रुटि संदेश तभी समझ आते हैं जब आपको पता हो कि उन्हें किस रास्ते ने पैदा किया।

इसे तय करने वाली तीन शर्तें

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

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

  • कंसोल पर व्यक्ति, कोई ऑटोमेशन नहीं: इंटरैक्टिव प्रॉम्प्ट।
  • बिना निगरानी शुरुआत, रहस्य संग्रहीत हो सकता है: मोड 0600 वाली क्रेडेंशियल फ़ाइल।
  • बिना निगरानी शुरुआत, रहस्य संग्रहीत नहीं हो सकता: प्रोसेस सब्स्टीट्यूशन या सीक्रेट एजेंट द्वारा लिखा गया fd।
  • क्लाइंट किसी दूसरी प्रक्रिया के स्वामित्व में है: प्रबंधन इंटरफ़ेस।

जब दो उत्तर बैठते हैं, तो वह चुनें जो रहस्य को argv और shell इतिहास से बाहर रखता है। प्रोग्राम आर्ग्युमेंट के रूप में दिया गया पासवर्ड प्रोसेस सूची के ज़रिए हर स्थानीय उपयोगकर्ता पढ़ सकता है, और इस ज़ाहिरीकरण को पलटना मुश्किल है।

हर इनपुट रास्ता असल में क्या करता है

--auth-user-pass अकेला कंसोल पर उपयोगकर्ता नाम और पासवर्ड मांगता है। फ़ाइल नाम दिए जाने पर क्लाइंट पहली पंक्ति को उपयोगकर्ता नाम और दूसरी पंक्ति को पासवर्ड मानता है; कोई भी चीज़ उद्धरण, टिप्पणी या कुंजी-मान सिंटैक्स का समर्थन नहीं करती। पूरा फ़ॉर्मैट यही है, इसलिए जो भी INI फ़ाइल की उम्मीद में इसे संपादित करता है, इसे तोड़ देता है। इनलाइन <auth-user-pass> ब्लॉक प्रोफ़ाइल के अंदर वही दो पंक्तियाँ रखता है, जिससे प्रोफ़ाइल स्वयं रहस्य बन जाती है और निजी कुंजी जैसी ही हैंडलिंग श्रेणी में आ जाती है।

बाकी दो रास्ते स्ट्रीम और सॉकेट हैं। OpenVPN को केवल पढ़ने योग्य फ़ाइल डिस्क्रिप्टर चाहिए, इसलिए वह प्रोसेस सब्स्टीट्यूशन, पाइप-आधारित /dev/fd प्रविष्टि या ऐसा फ़ाइल नाम स्वीकार करेगा जो वास्तव में FIFO है। प्रबंधन इंटरफ़ेस प्रकृति में अलग है: क्लाइंट मान खुद पढ़ने के बजाय किसी पर्यवेक्षक प्रक्रिया से पूछता है। यह अंतर फिर से जुड़ने पर मायने रखता है: क्रेडेंशियल फ़ाइल, वह FIFO जिसमें सीक्रेट सहायक फिर लिख सकता है, और प्रबंधन इंटरफ़ेस बिना व्यक्ति के फिर आपूर्ति कर सकते हैं; प्रोसेस सब्स्टीट्यूशन नहीं कर सकता, क्योंकि डिस्क्रिप्टर पहली बार पढ़ते ही खप जाता है।

फ़ाइल ठीक दो पंक्तियों की होनी चाहिए

दो विफलता-तरीके ज़्यादातर टूटी क्रेडेंशियल फ़ाइलों को कवर करते हैं। Windows एडिटर CRLF अंत छोड़ देता है, कैरिज रिटर्न पासवर्ड का हिस्सा बन जाता है, और सर्वर उस मान को अस्वीकार कर देता है जो स्क्रीन पर सही दिखता है। खाली दूसरी पंक्ति - वहाँ खाली पंक्ति जहाँ पासवर्ड होना चाहिए - क्लाइंट को खाली पासवर्ड के साथ छोड़ देती है, जिसे सर्वर अस्वीकार कर देता है, भले ही स्क्रीन पर मान सही दिखे। पासवर्ड के बाद अतिरिक्त नई पंक्ति हानिरहित है। फ़ाइल एडिटर से नहीं, shell से लिखें, और बाइट जाँचें:

install -m 600 /dev/null /etc/openvpn/client.creds
printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS" > /etc/openvpn/client.creds
od -c /etc/openvpn/client.creds | head -3

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

सर्वर को दोष देने से पहले फ़ाइल जाँचें। openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 चलाने पर छपता है कि फ़ाइल खुली या नहीं और बाद में कि क्रेडेंशियल स्वीकार हुए या नहीं, जो बताता है कि आगे कौन-सी परत बदलनी है।

स्ट्रीम, stdin और उनसे पैदा होने वाली त्रुटियाँ

पासवर्ड को पाइप में डालना ज़्यादातर लोगों की पहली कोशिश है और सबसे ज़्यादा आश्चर्य वाला रास्ता। प्रोसेस सब्स्टीट्यूशन काम करता है क्योंकि क्लाइंट को केवल पढ़ने योग्य डिस्क्रिप्टर चाहिए: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS")। /dev/stdin पास करना तभी काम करता है जब क्लाइंट के पूछने के क्षण stdin अभी खुला और पढ़ने योग्य हो, जो ऐसी पाइपलाइन में सच नहीं है जो उसे पहले ही खपा चुकी हो।

ERROR: could not read Auth username from stdin के दो अलग कारण हैं। कुछ 2.3.x क्लाइंट पर संदेश stdin हैंडलिंग के उस दोष से आया था जिसे बाद के 2.3 संस्करणों ने ठीक किया, इसलिए इतना पुराना क्लाइंट केवल अपग्रेड से सुधरता है। आधुनिक क्लाइंट पर वही वाक्यांश का अर्थ है कि क्लाइंट ने कंसोल इनपुट मांगा और stdin टर्मिनल नहीं था - ठीक वही स्थिति जो systemd यूनिट, cron कार्य या -t के बिना शुरू किए गए कंटेनर में होती है।

auth-nocache तीसरा लूप जोड़ता है जो टूटे पासवर्ड जैसा दिखता है। यह उपयोग के बाद क्रेडेंशियल स्मृति से हटा देता है, इसलिए नेटवर्क बदलाव से शुरू हुए पुनः कनेक्शन के पास दोहराने के लिए कुछ नहीं होता और प्रॉम्प्ट लौट आता है। यह वही निर्देश है जो डिज़ाइन के अनुसार काम कर रहा है। auth-nocache वह बदलता है जो क्लाइंट स्मृति में रखता है, यह नहीं कि सर्वर या पहचान प्रदाता खाते के बारे में क्या सोचता है, इसलिए पूरा समाधान वही फ़ाइल फिर आपूर्ति करना है, जिसे पुनः आरंभ पर फिर पढ़ा जाता है - और प्रबंधित कनेक्शन के लिए यह आपूर्ति स्वीकृत रहस्य-भंडार से आनी चाहिए, स्क्रिप्ट में रखे पासवर्ड से नहीं।

प्रबंधन इंटरफ़ेस, जब प्रॉम्प्ट किसी दूसरी प्रक्रिया के पास हो

जो नियंत्रक पहले से टनल की निगरानी करता है, वह उसके सवालों का जवाब भी दे सकता है। क्लाइंट को --management 127.0.0.1 7505 के साथ शुरू करें, स्थिति की पंक्तियाँ पढ़ें और >PASSWORD:Need 'Auth' username/password पर नज़र रखें। नियंत्रक अलग कमांड पंक्तियों पर username "Auth" alice और उसके बाद password "Auth" ... के साथ जवाब देता है। 'Auth' टोकन अनुरोध से पहचानकर्ता दोहराता है और मेल खाना चाहिए, वरना जवाब अनदेखा कर दिया जाता है और क्लाइंट प्रतीक्षा करता है।

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

क्रेडेंशियल समस्या जैसी दिखने वाली विफलताएँ

कभी पूरी न होने वाली TLS हाथ-मिलान, या VERIFY ERROR: depth=0, error=certificate signature failure, भरोसे की समस्या है और किसी भी उपयोगकर्ता नाम के पढ़े जाने से पहले होती है। UDP श्रोता की ओर इंगित proto tcp क्लाइंट उसी जगह विफल होता है: पैकेट कभी प्रमाणीकरण चरण तक नहीं पहुँचते, इसलिए हर पासवर्ड साहचर्य से गलत दिखता है। क्रेडेंशियल भेजे जाने से पहले प्रमाणपत्र सत्यापन चालू रखें; परिचित प्रॉम्प्ट यह नहीं बताता कि पासवर्ड कौन प्राप्त करता है। क्रेडेंशियल छूने से पहले प्रमाणपत्र श्रृंखला, सामान्य नाम और परिवहन जाँचें।

प्रोफ़ाइल जोड़ने वाली स्क्रिप्ट में shell की बगें दूसरा झूठा सुराग हैं। [ ! -f "$file" ] के अंदर गायब स्पेस command not found पैदा करता है, स्क्रिप्ट जल्दी रुक जाती है, प्रोफ़ाइल कभी फिर नहीं बनती, और क्लाइंट पिछली प्रोफ़ाइल के साथ शुरू होता है। वह त्रुटि shell की है, प्रमाणीकरण की नहीं, और पासवर्ड कितनी भी बार दोबारा टाइप करने से वह नहीं मिटेगी।

इस प्रवाह में हर प्रॉम्प्ट यह क्रेडेंशियल नहीं है। निजी कुंजी का पासफ़्रेज़, HTTP प्रॉक्सी लॉगिन और सेवा का पासवर्ड अलग-अलग चरणों में माँगे जाने वाले तीन अलग रहस्य हैं, और कुंजी पासफ़्रेज़ आमतौर पर auth-user-pass के बजाय क्लाइंट या एजेंट संभालता है। अगर प्रॉम्प्ट TLS सत्र बनने से पहले दिखे, तो आप गलत सवाल का जवाब दे रहे हैं और कोई खाता रीसेट मदद नहीं करेगा। गलत प्रॉम्प्ट हट जाने के बाद बाकी जाँचें सबसे पुरानी परत से शुरू होती हैं:

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

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

संबंधित लेख