OpenVPN में RAND_bytes विफल: लाइब्रेरी त्रुटि या गुम नोड
RAND_bytes विफलता का अर्थ अस्वीकृत एन्ट्रॉपी स्रोत या जेल में छिपा नोड हो सकता है। उपकरण बनाने से पहले त्रुटि कतार और प्रक्रिया का दृश्य पढ़ें।
RAND_bytes() failed एक स्थानीय आदिम के बारे में कथन है, खाते, पूर्व-साझा कुंजी या दूरस्थ पोर्ट के बारे में नहीं। दो बहुत अलग विफलताएँ वही पंक्ति उत्पन्न करती हैं और अलग साक्ष्य छोड़ती हैं। एक क्रिप्टोग्राफ़िक बैकएंड है जो बाइट्स जारी करने से मना करता है; दूसरी वह प्रक्रिया है जो उस एन्ट्रॉपी स्रोत तक नहीं पहुँचती जिसके लिए उसका कोड बनाया गया था। इन्हें अलग करने के लिए त्रुटि कतार की एक पढ़ाई और जेलबंद प्रक्रिया के फ़ाइल सिस्टम दृश्य पर एक नज़र चाहिए, और यह जाँच /dev के अंतर्गत कुछ भी बनाए जाने से पहले होनी चाहिए।
वापसी मान क्या अलग करता है
प्रलेखित अनुबंध तीन परिणाम अलग करता है, दो नहीं: सफलता के लिए 1, जब लोड किया गया RAND तरीका अनुरोध का समर्थन नहीं करता तो -1, और अन्य विफलताओं के लिए 0, जबकि व्याख्या त्रुटि कतार में रहती है। RAND_bytes संदर्भ एक ऐसा बिंदु जोड़ता है जिसे छोड़ना आसान है: डिफ़ॉल्ट जनरेटर समर्थित प्लेटफ़ॉर्म पर ऑपरेटिंग सिस्टम से बीज लेता है, और जब यह बीजारोपण विफल होता है तो वह पूर्वानुमेय बाइट्स लौटाने के बजाय त्रुटि अवस्था में रहता है।
उनमें से केवल एक संख्या वातावरण का वर्णन करती है। -1 निर्माण, प्रदाता या सुविधा का प्रश्न है, क्योंकि कोड ने कुछ ऐसा माँगा जो सक्रिय कार्यान्वयन प्रदान नहीं करता। बीजारोपण की शिकायत के साथ 0 वातावरण का प्रश्न है, क्योंकि जनरेटर एन्ट्रॉपी प्राप्त ही नहीं कर सका। संख्या अपने आप कभी नहीं बताती कौन-सी, और फ़ंक्शन का नाम भी नहीं।
जब छिपा उपकरण नोड असली कारण हो
सीमित सेवा उस शेल से अलग पेड़ देखती है जिसमें आप टाइप कर रहे हैं। chroot जेल, कंटेनर इमेज और कठोर किए गए unit फ़ाइलें नियमित रूप से ऐसा /dev प्रस्तुत करती हैं जिसमें मेज़बान से कम नोड होते हैं। यदि विफल कार्यान्वयन /dev/urandom को पथ नाम से खोलता है, तो यह अंतर शुरुआत तोड़ने के लिए पर्याप्त है जबकि मेज़बान स्वयं पूरी तरह स्वस्थ दिखता है। जेल के बाहर मौजूद उपकरण इस बात का कुछ सिद्ध नहीं करता कि जेलबंद प्रक्रिया को क्या खोलने की अनुमति है।
हालाँकि हर रैंडम इंटरफ़ेस को पथ की आवश्यकता नहीं होती। लिनक्स में getrandom सिस्टम कॉल न फ़ाइल नाम स्वीकार करती है न फ़ाइल डिस्क्रिप्टर, और उसका मैनुअल पृष्ठ नोट करता है कि यह गुण ठीक वहाँ उपयोगी है जहाँ chroot उपकरण पथ छिपाता है।
इसलिए गुम नोड की व्याख्या कोड की एक शाखा के बारे में परिकल्पना है, रैंडम संख्याओं के बारे में सामान्य नियम नहीं। जब साक्ष्य पथ का नाम लेते हैं तो यह टिकती है, और जब साक्ष्य कुछ और नाम लेते हैं तो यह अनुमान है।
पहले त्रुटि कतार पढ़ें, फिर प्रक्रिया का दृश्य
प्रश्न तय करने का सबसे तेज़ तरीका यह है कि लाइब्रेरी जो पहले से दर्ज कर चुकी है उसे पढ़ें, फिर सीधे जेल के भीतर के दृश्य को देखें। उस OpenSSL बिल्ड से शुरू करें जिसे सेवा ने वास्तव में लोड किया, क्योंकि प्रदाता स्टैक प्रमुख संस्करणों और वितरणों के बीच भिन्न होते हैं। फिर systemd से पूछें कौन-सी प्रक्रिया चल रही है और उस पर कौन-से प्रतिबंध लागू हैं। दोनों तथ्य मेज़ पर आने के बाद ही उन नोडों को सूचीबद्ध करना सार्थक है जिन्हें वह प्रक्रिया देख सकती है।
openssl version -a
systemctl show openvpn-server@lab -p MainPID -p PrivateDevices -p DevicePolicy
pid=$(systemctl show -p MainPID --value openvpn-server@lab)
sudo ls -l /proc/"$pid"/root/dev/urandom /proc/"$pid"/root/dev/random
ये पढ़ाइयाँ उसी प्रक्रिया पर करें, उस शेल पर नहीं जो संयोग से खुला है। मेज़बान के /dev की तुलना असंबंधित प्रक्रिया के दृश्य से करना वही तरीका है जिससे गलत निर्भरता दो बार ठीक होती है।
निर्भरता तभी जोड़ें जब आप उसका नाम ले सकें
जब साक्ष्य वास्तव में पथ का नाम लेते हैं, तो मरम्मत छोटी है: उसी एक पथ को जेल के भीतर उपलब्ध कराएँ और बाकी सब कुछ छोड़ दें। एक नोड का bind mount आमतौर पर पर्याप्त होता है, और mknod नोड के मानक major और minor नंबरों के साथ उन इंस्टॉलेशन पर वही परिणाम देता है जहाँ mount कोई विकल्प नहीं है। सैंडबॉक्स का विस्तार, हर कैरेक्टर डिवाइस तक पहुँच देना या PrivateDevices बंद करना लक्षित सुधार को स्थायी सुरक्षा प्रतिगमन से बदल देता है।
एन्ट्रॉपी डेमॉन उस मरम्मत का विकल्प नहीं है। haveged जैसे पैकेज बदलते हैं कि कर्नेल पूल कैसे पोषित होता है; वे ऐसा पथ नहीं बना सकते जिसे जेलबंद प्रक्रिया खोल सके। इनमें से एक स्थापित करना स्वास्थ्य ग्राफ़ को बेहतर दिखा सकता है जबकि खोलने की कॉल अभी भी विफल रहती है। दोनों समस्याओं को अलग रखें, वरना अगली विफलता फिर गलत परत को दी जाएगी।
जनरेटर और सुरंग को अलग-अलग सत्यापित करें
पुनः आरंभ ही एकमात्र परीक्षण है जो वही कॉन्फ़िगरेशन, वही unit फ़ाइल और वही सीमाबद्धता दोबारा उपयोग करता है जिन्होंने विफलता उत्पन्न की। इसे चलाएँ, फिर पहले के बूट के नमूने के बजाय जर्नल की सबसे नई प्रविष्टियाँ पढ़ें।
sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'
उस आउटपुट में दो अलग चीज़ें खोजें: रैंडम स्रोत के संदेश का गायब होना, और सुरंग का अपने सामान्य आरंभिक पड़ाव तक पहुँचना। फिर से काम करने वाला जनरेटर एक स्थानीय विफलता हटाता है और सर्वर की पहचान, क्रेडेंशियल या रूटिंग के बारे में कुछ नहीं कहता। इसे उसी क्लाइंट कॉन्फ़िगरेशन से जाँचें जो पहले विफल हुआ था, ताकि परिणाम तुलनीय हो, केवल बेहतर न हो।