हुक तुम्ही तो root म्हणून हाताने चालवता तेव्हा चालतो आणि परत देतो Operation not permitted त्या क्षणी, जेव्हा सेवा तो सुरू करते. या दोन धावांमध्ये फाइल बदलली नाही; वातावरण बदलले. systemd प्रक्रियेला लहान जग देते: कमी क्षमता, वेगळे /dev, फक्त-वाचन फाइलसिस्टम मार्ग आणि कामांची वरची मर्यादा. अपयशाला एक विशिष्ट क्रिया नाकारणारी सीमा म्हणून वाचा, तुटलेली स्क्रिप्ट म्हणून नाही.

जी क्रिया नाकारली गेली तिथून सुरुवात करा

unit अयशस्वी झाला असे सांगणारी लॉग ओळ तुम्हाला जवळपास काहीच सांगत नाही. उपयुक्त ओळ नाकारलेल्या कॉलचे नाव घेते: उघडता न आलेला डिव्हाइस नोड, ज्यात लिहिता आले नाही असे डिरेक्टरी, तयार होऊ न शकलेली namespace. एकही निर्देशाला हात लावण्यापूर्वी तो कॉल शोधा, कारण प्रत्येक वेगळ्या मर्यादेशी जुळतो. नंतर पॅकेजने पाठवलेली फाइल नव्हे, तर प्रत्यक्ष चाललेला unit वाचा, drop-in सह.

खालील क्वेरी फ्रॅगमेंट मार्ग, drop-in डिरेक्टरी आणि डिव्हाइस किंवा फाइलसिस्टम नाकारण्यासाठी महत्त्वाचे गुणधर्म छापते. कोणती सीमा संबंधित आहे हे ठरवण्यापूर्वी सर्व वाचा:

systemctl show "[email protected]" -p FragmentPath -p DropInPaths -p PrivateDevices -p DevicePolicy -p DeviceAllow -p ProtectHome -p ProtectSystem -p TasksMax
journalctl -u "[email protected]" -b --no-pager | grep -iE 'operation not permitted|permission denied|cannot open|failed'

त्या ब्लॉकमध्ये काहीही लिहित नाही. नाकारलेला कॉल जर्नलमध्ये नसल्यास, निर्देशांचा अंदाज लावण्याऐवजी एका धावेसाठी क्लायंटची तपशीलवारता वाढवा. चालू असलेली प्रक्रिया unit सुरू झाला हे सिद्ध करते, हुक आवश्यक विशेषाधिकारांसह चालला हे नाही.

namespace ला TUN डिव्हाइस कधीही न वापरणारे mount अधिकार लागतात

एकाच हुकमध्ये सारखे दिसणाऱ्या दोन क्रियांची परवानगी प्रोफाइल वेगळी असते. /dev/net/tun उघडणे आणि इंटरफेस तयार करण्यासाठी नेटवर्क प्रशासन आणि त्या नोडमधील प्रवेश लागतो. नाव असलेली नेटवर्क namespace तयार करण्यासाठीही mount काम लागते, कारण namespace साधन नवीन /sys दृश्य mount करते आणि स्थिती डिरेक्टरी तिच्या जागी बांधते. अपस्ट्रीम क्लायंट unit mount प्रशासन जाणीवपूर्वक त्याच्या सीमा संचाबाहेर ठेवतो, म्हणून namespace टप्पा नाकारला जातो, तर बोगदा स्वतः चालला असता.

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

तुमच्या shell मधील चाचणी अमर्यादित root कडे असलेली प्रत्येक क्षमता वारशाने घेते, आणि unit त्याच्या सीमा संचाने ठेवलेले घेते. त्या दोन धावा वेगळे प्रयोग आहेत बाइनरी एकसारखी असली तरी.

डिव्हाइस, संरक्षित मार्ग आणि कामांच्या वरच्या मर्यादा

नाकारलेली क्रिया माहीत झाल्यावर, तीन निर्देश गट बहुतेक अपयशे स्पष्ट करतात. डिव्हाइसना प्रवेश नियंत्रित करते PrivateDevices, जे /dev ला किमान स्यूडो-डिव्हाइस संचाने बदलते, आणि DevicePolicy सह DeviceAllow, जे cgroup काय परवानगी देते हे ठरवतात. /dev/net/tun त्या किमान संचाचा भाग नाही, म्हणून PrivateDevices=yes असलेला unit डिव्हाइस धोरण काहीही म्हणो, तो उघडू शकत नाही.

फाइलसिस्टम संरक्षण दुसऱ्या प्रश्नाचे उत्तर देते. ProtectHome=yes करते /home, /root आणि /run/user अगम्य करते, आणि ProtectSystem=full करते /usr, /boot आणि /etc फक्त-वाचन करते. म्हणून स्वतःच्या कॉन्फिगरेशन फाइलजवळ लिहिणारा हुक तुमच्या shell मध्ये चालतो आणि unit अंतर्गत अयशस्वी होतो, गहाळ क्षमतेसारख्याच परवानगीच्या स्वरूपात. लिहिता येणारे इनपुट धोरण परवानगी देते त्या मार्गावर हलवा, किंवा अरुंद ReadWritePaths= नोंद जोडा.

संसाधन मर्यादा तिसरा गट आहे, आणि सर्वात कमी स्पष्ट. TasksMax= unit किती कामे तयार करू शकतो हे मर्यादित करते, आणि फाइल डिस्क्रिप्टरची वरची मर्यादा socket आणि हँडलसाठी तशीच वागते. मर्यादेपलीकडे वाढलेली तैनाती परवानगी त्रुटीऐवजी संसाधन त्रुटीने अयशस्वी होते, म्हणूनच अचूक संदेश अजूनही महत्त्वाचा आहे.

namespace टप्पा हुकमधून बाहेर काढा

क्लायंटकडे नसावा अशा विशेषाधिकाराची गरज असणारी तयारी त्याच्या स्वतःच्या unit मध्ये येते. क्लायंटपूर्वी चालणारा, त्याचा निकाल ठेवणारा आणि जोडणीपूर्वी क्रमाने ठेवलेला oneshot namespace टप्प्याला आवश्यक ते देतो, ते अधिकार बोगदा प्रक्रियेला न देता. नंतर क्लायंट स्वतःच्या up हुकमधून स्क्रिप्ट बोलावण्याऐवजी त्या unit चा संदर्भ देतो.

खालील टेम्पलेट सुरुवातीचे स्वरूप आहे, न वाचता लागू करण्यासारखे नाही. ते तयारी विशेषाधिकार जिथे राहतो तिथेच ठेवते आणि बोगदा unit ला हात न लावता सोडते:

# /etc/systemd/system/[email protected]
[Unit]
Description=Namespace preparation for %i
Before=openvpn-client@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/netns-up.sh %i
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN
[Install]
WantedBy=multi-user.target

पॅकेज केलेला unit संपादित करण्याऐवजी drop-in ने क्रम जोडा, जेणेकरून अपग्रेड तुमचा बदल गुपचूप टाकू शकणार नाही. डिरेक्टरी इन्स्टन्स नावाशी जोडलेली आहे, म्हणून दुसऱ्या प्रोफाइलला स्वतःची फाइल लागते:

sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/10-namespace.conf >/dev/null <<'CONF'
[Unit]
[email protected]
[email protected]
CONF
sudo systemctl daemon-reload

बदलानंतर तोच कॉल पुन्हा करा

तोच कॉल वेगळा निकाल देतो तेव्हाच दुरुस्ती निश्चित होते. दोन्ही unit पुन्हा सुरू करा, अयशस्वी झालेली क्रिया चालवा, आणि तिचा निकाल बदलापूर्वी जतन केलेल्या जर्नल ओळीशी तुलना करा. हुक पुन्हा कधीही न चालता unit सुरू होणे ही दुरुस्ती नाही.

खालील क्रम तुलना प्रामाणिक ठेवतो, कारण तो unit चा रंग नव्हे, नाकारलेला कॉल तपासतो. त्याचे आउटपुट बदलापूर्वी पकडलेल्या जर्नल ओळीजवळ जतन करा:

sudo systemctl restart "[email protected]" "[email protected]"
systemctl status "[email protected]" --no-pager
journalctl -u "[email protected]" -b --no-pager | grep -c 'Operation not permitted'
ip -brief addr show tun0

शेवटची ओळ वाचण्याऐवजी नकार मोजा, कारण हुक अयशस्वी होऊ शकतो, पुन्हा प्रयत्न करू शकतो आणि यशस्वी होऊ शकतो, आणि सीमा हलली का हे फक्त मोजणी दाखवते. drop-in मध्ये तुम्ही सैल केलेला निर्देश आणि कारण नमूद करणारी टिप्पणी ठेवा, कारण पुढील अपग्रेड तुमची कॉन्फिगरेशन पॅकेजच्या डीफॉल्टशी तुलना करते. सर्व संरक्षण बंद केल्यावरच सुरू होणारा unit दुरुस्त झालेला नाही.

संबंधित लेख