तपाईंको OpenVPN हुक कुन systemd स्यान्डबक्सले अस्वीकार गर्यो भनेर कसरी पत्ता लगाउने
हुक root को रूपमा चल्छ र systemd मुनि असफल हुन्छ, किनभने unit ले कम क्षमता, सानो /dev र पढ्न-मात्र मार्गहरू राख्छ।
हुक तपाईंले यसलाई 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 सुधारिएको छैन।