VPN कनेक्शन के बाद की कार्रवाई उपयोगकर्ता के रूप में चलाएँ, डेमन के रूप में नहीं
USER=alice कहने वाला पर्यावरण चर यह नहीं बदलता कि hook किस खाते के रूप में चलता है। घटना, ट्रिगर और कार्रवाई अलग करें, फिर UID सिद्ध करें।
VPN डेमन पर कनेक्शन hooks डेमन के रूप में चलते हैं, और आम तौर पर इसका अर्थ है कि वे root के रूप में चलते हैं। जिस पल उनमें से कोई hook किसी की होम डायरेक्टरी में लिखता है या डेस्कटॉप सहायक को फिर से शुरू करता है, आपने एक नेटवर्क घटना को किसी भी स्थानीय उपयोगकर्ता के रूप में कार्य करने की क्षमता दे दी है। सामान्य छोटा रास्ता, यानी पर्यावरण चर से उपयोगकर्ता नाम पढ़कर उसे आगे भेजना, इसे ठीक नहीं करता। यह कार्रवाई को फिर से लेबल करता है, पर यह नहीं बदलता कि कौन-सा खाता उसे निष्पादित करता है। जो काम करता है वह तीन भागों वाला हस्तांतरण है, जिसमें विशेषाधिकार प्राप्त चरण बताता है कि क्या हुआ और एक अलग इकाई सही पहचान के अंतर्गत कार्रवाई करती है।
पर्यावरण में उपयोगकर्ता नाम कोई पहचान स्विच नहीं है
Unix तय करता है कि कोई प्रक्रिया क्या छू सकती है, उसके प्रभावी उपयोगकर्ता ID से, उसके पर्यावरण के स्ट्रिंग से नहीं। USER=alice सेट करना या LOGNAME निर्यात करना बदलता है कि लापरवाह सॉफ़्टवेयर अपने आउटपुट में क्या छापता है; फ़ाइल स्वामित्व जाँचों में यह कुछ नहीं बदलता। उस चर के साथ root के रूप में चलने वाला hook फिर भी Alice की फ़ाइलें root के रूप में ही खोलता है।
नाम भी एक ही नाम नहीं हैं। दूरस्थ पहुँच लॉगिन, स्थानीय Unix खाता और प्रमाणपत्र का सामान्य नाम तीन पहचानकर्ता हैं जो अक्सर मेल खाते हैं और कभी-कभी नहीं। a.smith के रूप में प्रमाणित होने वाले उपयोगकर्ता के पास कोई स्थानीय खाता ही न हो, या वह निर्देशिका सेवा के माध्यम से asmith पर मैप हो जाए। कोई भी ऐसा डिज़ाइन जो मानता है कि एक स्ट्रिंग तीनों भूमिकाएँ निभाती है, पहले ठेकेदार पर टूट जाएगा।
इसलिए पहला प्रश्न «कौन-सा उपयोगकर्ता जुड़ा है» नहीं, बल्कि «कौन-सा स्थानीय खाता यह कार्रवाई करने की अनुमति रखता है» है। इसका उत्तर अपने खाता डेटाबेस से दें, क्लाइंट द्वारा भेजे गए डेटा से नहीं:
id -u alice
getent passwd alice | cut -d: -f1,3,6
stat -c '%U:%G %a %n' /home/alice/.local/state/vpn-status.json
तीसरा आदेश वही है जिसे लोग छोड़ देते हैं। यदि लक्ष्य फ़ाइल root की स्वामित्व वाली है क्योंकि पिछले hook ने उसे बनाया था, तो सही ढंग से कॉन्फ़िगर की गई उपयोगकर्ता कार्रवाई अनुमति त्रुटि से विफल होगी जो systemd समस्या जैसी दिखती है और है नहीं।
डेमन अपनी जगह पर रहता है
VPN सेवा के अपने User= को Alice पर बदलना गलत लीवर है। यह बदलता है कि डेमन इंटरफ़ेस कैसे बाइंड करता है, कुंजियाँ कैसे पढ़ता है, अपनी स्थिति फ़ाइल कैसे लिखता है और रूट कैसे प्रबंधित करता है, और यह पूरा जोखिम उस इकाई में डाल देता है जो काम कर रही थी। डेमन को अपने विशेषाधिकार चाहिए; बाद की कार्रवाई को नहीं।
इकाई को छूने से पहले देखें कि वह वास्तव में क्या कर रही है। दो आदेश आपको निष्पादन पहचान और लागू सटीक आदेश पंक्तियाँ बताते हैं, जिसमें ओवरराइड द्वारा जोड़ा गया सब कुछ भी शामिल है:
systemctl show -p User -p Group -p ExecStart openvpn-server@server
systemctl cat openvpn-server@server
डिफ़ॉल्ट पैकेज इंस्टॉल पर डेमन root होता है और --up स्क्रिप्ट उसे विरासत में पाती है। इसे मानने के बजाय पुष्टि करें, क्योंकि कठोर किया गया वितरण इसे समर्पित खाते पर ले जा चुका हो सकता है, और हाथ से लिखा drop-in hook को भिन्न नियमों वाले रैपर से चला सकता है।
तीन नामित भाग, एक संकीर्ण ट्रिगर
रखरखाव में टिकने वाली व्यवस्था में घटना, ट्रिगर और कार्रवाई होती है। डेमन बताता है कि एक नामित सत्र ऊपर आया। ट्रिगर उस छोटे तथ्य को स्वीकार करता है और एक निश्चित कार्रवाई माँगता है। कार्रवाई उस स्थानीय खाते के अंतर्गत चलती है जिसके स्वामित्व में वे फ़ाइलें हैं जिन्हें वह छूती है। श्रृंखला में कुछ भी मनमाना आदेश पथ स्वीकार नहीं करता।
कार्रवाई स्वयं एक सामान्य सेवा इकाई है, और पहचान उसके भीतर एक निर्देश है:
[Service]
Type=oneshot
User=alice
Group=alice
ExecStart=/usr/local/bin/refresh-vpn-status --slot %i
ध्यान दें कि User=alice पूरी इकाई पर लागू होता है, और systemd एक अपवाद दर्ज करता है जिसे जानना चाहिए: + उपसर्ग वाला आदेश इस पर ध्यान दिए बिना पूर्ण विशेषाधिकारों से चलता है। वह उपसर्ग एक अकेले विशेषाधिकार प्राप्त चरण के लिए वैध औज़ार है और अभी बनाए गए पृथक्करण को रद्द करने का सुविधाजनक तरीका, इसलिए उस इकाई में किसी भी + को समीक्षा में उचित ठहराने योग्य चीज़ मानें।
ट्रिगर का इनपुट न्यूनतम और गैर-गुप्त रखें। सत्र पहचानकर्ता, मैप किया गया खाता और एक समय-चिह्न आम तौर पर वह सब कुछ हैं जो चाहिए। कभी भी शेल अंश, निष्पादन योग्य फ़ाइल का पथ या क्लाइंट द्वारा दिया गया पर्यावरण ब्लॉक सीमा के पार न भेजें, क्योंकि प्राप्त करने वाले पक्ष के पास वैध मान और इंजेक्ट किए गए मान में अंतर करने का कोई तरीका नहीं है।
उस पहचान को सत्यापित करें जो वास्तव में चली
कॉन्फ़िगरेशन समीक्षा प्रमाण नहीं है। स्वीकृत परीक्षण कनेक्शन के बाद, उस UID की पुष्टि करें जिसने फ़ाइल को छुआ और उस UID की जिसका डेमन अभी भी उपयोग कर रहा है:
stat -c '%U %G %y %n' /home/alice/.local/state/vpn-status.json
ps -o user=,pid=,cmd= -p "$(pgrep -o -f 'openvpn --daemon')"
systemd-run --uid=alice --pipe /usr/local/bin/refresh-vpn-status --dry-run
पहली पंक्ति में Alice और आपकी परीक्षण विंडो के भीतर एक समय-चिह्न दिखना चाहिए। दूसरी में अभी भी root या पैकेज का सेवा खाता दिखना चाहिए, जो सिद्ध करता है कि डेमन हिला नहीं। तीसरी वास्तविक पुनःकनेक्शन की प्रतीक्षा किए बिना कार्रवाई की अनुमतियाँ जाँचने का सबसे सस्ता तरीका है।
यदि फ़ाइल का स्वामी Alice है पर उसका समूह या मोड चलाने के बीच बदल गया है, तो तर्क त्रुटि के बजाय UMask= या डायरेक्टरी अनुमति का अंतर खोजें। यदि समय-चिह्न बिल्कुल नहीं हिला, तो ट्रिगर कभी चला ही नहीं, और उपयोगी अगला कदम दूसरा क्लाइंट पुनःकनेक्शन नहीं, बल्कि कार्रवाई इकाई के लिए journalctl -u है।
कनेक्शन घटना अभी भी क्या सिद्ध नहीं करती
स्थापित टनल एक तथ्य है। इसका अर्थ यह नहीं है कि डेस्कटॉप सत्र खुला है, सत्र बस पहुँच योग्य है, या कार्रवाई जो निजी संसाधन चाहती है वह अब उपलब्ध है। Alice के UID के अंतर्गत oneshot इकाई के पास उसकी पहचान है और उसके सत्र से कुछ नहीं, इसलिए ग्राफ़िकल बस चाहने वाली हर चीज़ को समर्थित उपयोगकर्ता-सत्र तंत्र से गुज़रना होगा और यह परिभाषित करना होगा कि वह लॉग आउट होने पर क्या होता है।
पुनःकनेक्शन भी दोहराए जाते हैं। ट्रेन में सोया लैपटॉप एक घंटे में एक दर्जन कनेक्शन घटनाएँ पैदा कर सकता है, और हर बार एक पंक्ति जोड़ने वाला hook स्थिति फ़ाइल को ऐसे लॉग में बदल देता है जिसे कोई पढ़ नहीं सकता। कार्रवाई को इडेम्पोटेंट बनाएँ, या उसे सत्र-कुंजी वाला एक ही रिकॉर्ड बदलने दें।
अंत में, इकाई के भीतर ही क्षति की त्रिज्या सीमित करें: स्थिति डायरेक्टरी से अलग केवल-पढ़ने योग्य फ़ाइलसिस्टम दृश्य, कोई नए विशेषाधिकार नहीं, और एक स्पष्ट समय-सीमा। डेमन और उपयोगकर्ता कार्रवाई के बीच पृथक्करण अपने आप में मूल्यवान है, पर जब कार्रवाई आपके द्वारा स्वीकृत उस एक चीज़ के अलावा कुछ नहीं कर सकती तब यह कहीं अधिक मूल्यवान है।