सेवा शुरू होती है, प्रोफ़ाइल को बिना किसी शिकायत के पढ़ती है और फिर ऐसी पंक्ति पर मर जाती है जो असंबंधित लगती है: वह ca.crt नहीं खोल सकती। प्रमाणपत्र में कुछ नहीं बदला, और unit फ़ाइल में प्रोफ़ाइल का पथ पूर्ण है। यही संयोजन संकेत है। आपने जो पथ दिया वह एक फ़ाइल का पता लगाता है, और उस फ़ाइल के अंदर के नाम पूरी तरह कहीं और हल होते हैं, इसलिए पूर्ण रूप से योग्य दिखने वाला लॉन्च भी ऐसी निर्देशिका से अपनी कुंजियाँ पढ़ सकता है जिसकी किसी ने मंशा नहीं की थी।

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

प्रोफ़ाइल का पथ आधार निर्देशिका नहीं है

/tmp में शुरू होने वाली और /etc/vpn/prod/tenant-a.ovpn पाने वाली प्रक्रिया की कल्पना करें। उस प्रोफ़ाइल के अंदर, पंक्ति ca ca.crt एक सापेक्ष पथ बताती है। प्रोफ़ाइल को खोजने वाले तर्क में कुछ भी उस नाम को फिर से नहीं लिखता, इसलिए प्रक्रिया /tmp/ca.crt खोजती है और अनुपस्थित फ़ाइल की सूचना देती है।

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

मैनुअल क्या अलग करता है: --config और --cd

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

openvpn --cd /etc/vpn/prod --config tenant-a.ovpn

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

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

सेवा कहीं और शुरू होती है

प्रोफ़ाइल निर्देशिका में इंटरैक्टिव शेल पैकेज्ड unit के बारे में कुछ साबित नहीं करता। प्रबंधक अपनी कार्य निर्देशिका तय करते हैं, और रैपर स्क्रिप्ट बाइनरी चलने से पहले उसे फिर से बदल सकती है। विफल होने वाली unit ही एकमात्र लॉन्च है जिस पर तर्क करना लायक है।

systemctl show -p WorkingDirectory -p ExecStart --value openvpn@tenant-a
ls -l /proc/$(pgrep -n openvpn)/cwd

दूसरा कमांड वह निर्देशिका दिखाता है जो जीवित प्रक्रिया वास्तव में थामे हुए है, और रैपर शामिल होने पर यह unit फ़ाइल से अधिक भरोसेमंद है। यदि दोनों सहमत न हों, तो उत्तर रैपर है और unit भ्रामक निशान है।

खोज के बाद: अनुमतियाँ, chroot और सैंडबॉक्सिंग

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

तीन सामान्य रूप समान त्रुटि पैदा करते हैं। फ़ाइल केवल root के लिए पठनीय है जबकि सेवा उसे खोलने से पहले विशेषाधिकार छोड़ देती है। unit एक ऐसा सुरक्षात्मक फ़ाइलसिस्टम दृश्य सेट करती है जिसमें प्रोफ़ाइल निर्देशिका शामिल नहीं है। डेमन chroot के साथ चलता है, इसलिए होस्ट पर मौजूद पथ उस दृश्य के अंदर मौजूद नहीं है।

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

अपने स्वयं के लॉन्च से सुधार सिद्ध करें

प्रोफ़ाइल से असंबंधित निर्देशिका से असली unit को पुनः आरंभ करें और वही स्टार्टअप पंक्ति देखें। फिर पुष्टि करें कि प्रक्रिया चलते समय इच्छित निर्देशिका थामे हुए है और उसने जो प्रमाणपत्र लोड किया वही आपकी अपेक्षा है।

systemctl restart openvpn@tenant-a
systemctl status openvpn@tenant-a --no-pager
journalctl -u openvpn@tenant-a -n 20 --no-pager

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

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

संबंधित लेख