OpenVPN errno 2 तक्रारीसह थांबते, ती /dev/net/tun बद्दल आहे, तर lsmod tun मॉड्यूल सहजपणे सूचीबद्ध करते. दोन्ही तथ्ये एकाच वेळी खरी आहेत. मॉड्यूल ड्रायव्हर देतो, आणि क्लायंट जो मार्ग उघडतो तो डिव्हाइस नोड आहे जो दुसऱ्या कशालातरी तयार करावा लागतो. दोन्हींना एकच वस्तू मानणे हेच कारण आहे की मॉड्यूल पुन्हा लोड करण्याचा स्पष्ट उपाय काहीच बदलत नाही.

दोन वस्तू, दोन वेगळे मालक

कर्नेल मॉड्यूल आणि डिव्हाइस नोड स्वतंत्र जीवनचक्र असलेल्या स्वतंत्र वस्तू आहेत. मॉड्यूल लोड केल्याने ड्रायव्हर नोंदवला जातो, आणि devtmpfs असलेल्या सिस्टममध्ये कर्नेल संबंधित नोड तयार करण्यास सांगते. devtmpfs नसलेल्या सिस्टममध्ये काहीच काही तयार करत नाही, आणि ड्रायव्हर त्याकडे दाखवणाऱ्या कोणत्याही मार्गाशिवाय तिथे बसतो. मॉड्यूल एकाच क्षणी लोड केलेले, निरोगी आणि फाइलसिस्टममधून पूर्णपणे अगम्य असू शकते.

म्हणूनच त्रुटीचा मजकूर आणि मॉड्यूल यादी एकमेकांना विरोध करत नाहीत. क्लायंट मार्ग उघडतो, मार्ग नाही, आणि tun ड्रायव्हरला विचारण्यापूर्वीच कर्नेल ENOENT परत करते. मॉड्यूल पुन्हा लोड केल्याने गहाळ मार्ग दुरुस्त होत नाही, आणि मार्ग तयार केल्याने गहाळ ड्रायव्हर दुरुस्त होत नाही.

lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts

devtmpfs विरुद्ध स्पष्ट mknod

सामान्यतः दोन यंत्रणा तो नोड तयार करतात, आणि कोणती जबाबदार असावी हे माहीत असल्यास काय दुरुस्त करायचे ते कळते. devtmpfs कर्नेलला माउंट केलेल्या इन्स्टन्समध्ये डिव्हाइस नोड तयार करू देतो, आणि udev त्यांच्यावर मालकी आणि परवानग्या लागू करते. एक स्पष्ट mknod बूटच्या वेळी दोन्हीपैकी कोणीही चालत नाहीत अशा इमेज आणि नेमस्पेससाठी हाताने करायचा मार्ग आहे.

हेतूंची नाही, परिणामांची तुलना करा. devtmpfs /dev वर माउंट असूनही नोड अजूनही नसल्यास, ड्रायव्हर तुम्ही गृहीत धरतात तो नाही, किंवा काहीतरी बूटनंतर नोड काढून टाकले. /dev उघडलेल्या rootfs मधील साधी डिरेक्टरी असल्यास, कोणतीही स्वयंचलित यंत्रणा नाही आणि इमेज बनवणाऱ्याला नोड तयार करावा लागतो.

stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8

दोन्ही यंत्रणा चालत नाहीत तिथे नोड हाताने तयार करावा लागतो, आणि क्रम महत्त्वाचा आहे. प्रथम पालक डिरेक्टरी तयार करा, कारण mknod ती शोधून काढू शकत नाही, नंतर अक्षर उपकरण, नंतर root ला केवळ लिहिण्यायोग्य ठेवणारी पद्धत. नोड तयार करण्यापूर्वी मॉड्यूल पुन्हा लोड करा, आणि विद्यमान मार्ग ls तो उपकरण नाही, डिरेक्टरी आहे हे दाखवल्यानंतरच काढा.

sudo modprobe tun
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 600 /dev/net/tun
ls -l /dev/net/tun

सर्वात वेगवान भेदक stat नोंदवतो तो प्रकार आहे, आणि त्या मार्गावर डिरेक्टरी असणे हे किमान इमेजमध्ये सर्वात सामान्य आश्चर्य आहे. चांगल्या हेतूने लिहिलेले mkdir Dockerfile मध्ये तेच सोडते, आणि कितीही मॉड्यूल लोड केले तरी डिरेक्टरी अक्षर उपकरणाने बदलता येत नाही. Major 10 आणि minor 200 ही tun साठी नोंदवलेली जोडी आहे, हेक्समध्ये a आणि c8 अशी व्यक्त केली जाते.

चार खुणा, चार कारणे

चार कारणे जवळपास प्रत्येक प्रकरण स्पष्ट करतात, आणि प्रत्येक लॉगमध्ये वेगळी खूण सोडते. बूट पर्यावरणापासून सुरुवात करा. डिस्कविरहित इमेज, एम्बेडेड बोर्ड आणि initramfs टप्पे बहुतेक वेळा devtmpfs किंवा udev-व्यवस्थापित /devमाउंट करत नाहीत, त्यामुळे कोणतीही प्रक्रिया कधीही नोड लिहीत नाही. नंतर /devहोस्ट करणाऱ्याचे माउंट पर्याय वाचा, कारण nodev मार्ग अस्तित्वात राहू देतो पण तो उघडण्यास नकार देतो, आणि कठोर केलेल्या होस्टवरून घेतलेले bind माउंट स्वतःची घोषणा न करता हा फ्लॅग बाळगते. फक्त-वाचन माउंट अधिक लवकर आणि मोठ्याने अयशस्वी होते: mknod तिथे EROFS परत करते, तर EPERM म्हणजे प्रक्रियेकडे क्षमता नाही, फाइलसिस्टम स्वतःचे रक्षण करत आहे असे नाही. शेवटी, स्वतःच्या /dev tmpfs असलेल्या कंटेनर रनटाइमला नोड त्याच्या स्वतःच्या नेमस्पेसमध्ये इंजेक्ट करावा लागतो, आणि त्याच्या डिव्हाइस cgroup ने major आणि minor जोडीला परवानगी द्यावी.

परवानग्या पुन्हा बदलण्यापूर्वी धोरण स्तर तपासा. SELinux आणि AppArmor फाइलचे प्रत्येक गुणधर्म अनुमती देत असलेले उघडणे नाकारू शकतात, आणि तो नकार क्लायंट आउटपुटमध्ये नाही तर ऑडिट लॉगमध्ये दिसतो. कोणत्याही नकारात कधीही न दिसणारा परवानगी बदल पूर्णपणे चुकीच्या स्तरावर घालवलेला वेळ आहे.

sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5

यादीने नाही, इंटरफेसने सिद्ध करा

यशस्वी यादी सिद्ध करते की मार्ग अस्तित्वात आहे आणि त्यापेक्षा जास्त काही नाही. निरोगी tun नोड वाचनासाठी उघडा आणि कॉल त्रुटीसह परत येतो, कारण उपकरणाला वाचनाची सिमँटिक्स नाही आणि ती साधी फाइल नाही. तीच त्रुटी येथे यशाची खूण आहे, आणि ती ओळखल्याने तुम्ही तिला बिघाड मानून मागे लागत नाही.

head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state

निर्णायक चाचणी इंटरफेस तयार करते, कारण ती एकाच पायरीत ड्रायव्हर, नोड आणि तुमचे विशेषाधिकार तपासते. जोडणी यशस्वी झाली आणि दुवा दिसला तर तिन्ही काम करत आहेत. ती अयशस्वी झाल्यास errno कारणे वेगळी करते: ENOENT म्हणजे वापरण्यायोग्य नोड नाही, EPERM क्षमता, माउंट फ्लॅग किंवा धोरणाकडे निर्देश करते, आणि EBUSY म्हणजे दुसऱ्या प्रक्रियेकडे इंटरफेस आधीच आहे.

sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun

ती चाचणी प्रत्यक्षात अयशस्वी होणाऱ्या संदर्भातच चालवा, कारण सेवा एकक, कंटेनर किंवा नियोजित काम तुमच्या लॉगिन शेलपेक्षा वेगळा क्षमता संच बाळगू शकते. चुकीच्या संदर्भात उत्तीर्ण होणारी चाचणी अयशस्वी होणाऱ्या संदर्भाबद्दल काहीही सिद्ध करत नाही.

जेव्हा उपकरण समस्या नाही

इंटरफेस चाचणी यशस्वी झाली आणि क्लायंट अजूनही अयशस्वी होत असेल, तर उरलेली समस्या प्रोफाइल, सेवा संदर्भ किंवा मार्ग आहे, आणि उपकरण ठीक आहे. तोच डिव्हाइस नोड संपादित करणे थांबवण्याचा क्षण आहे, कारण पुढील बदल कार्यरत सिस्टमपासून अंतरच वाढवतात.

प्रत्येक वेळी नवीन शोधण्याऐवजी त्या पाच तपासण्या चालवा: मॉड्यूल प्रतिस्पर्धी मॉड्यूलशिवाय लोड आहे का, मार्ग योग्य major आणि minor असलेले अक्षर उपकरण आहे का, माउंट पर्याय स्वच्छ आहेत का, प्रक्रिया संदर्भात क्षमता आहे का, आणि अयशस्वी होण्याच्या वेळी धोरण नकार आहे का. पाचही पार करणारा बिघाड उपकरणाची समस्या नाही, संदेश काहीही सांगो.

संबंधित लेख