गैर-रूट प्रक्रिया को 80 और 443 पोर्ट में बाँधने की अनुमति दें?


104

क्या एक कर्नेल पैरामीटर को ट्यून करना संभव है ताकि एक यूजरलैंड प्रोग्राम को 80 और 443 पोर्ट के लिए बाध्य किया जा सके?

मेरे द्वारा पूछे जाने का कारण मुझे लगता है कि एक सॉकेट खोलने और सुनने के लिए एक विशेषाधिकार प्राप्त प्रक्रिया की अनुमति देना इसकी मूर्खता है। जो कुछ भी सॉकेट खोलता है और उच्च जोखिम होता है, और उच्च जोखिम वाले अनुप्रयोगों को रूट के रूप में नहीं चलना चाहिए।

मैं बहुत कुछ पता लगाने की कोशिश करता हूं कि रूट विशेषाधिकार के साथ खराब मालवेयर को हटाने की बजाय पोर्ट 80 पर सुन रही प्रक्रिया क्या है।


1
Serverfault.com/questions/268099 और stackoverflow.com/questions/413807 देखें । संक्षिप्त जवाब नहीं है।
सामी Laine

10
लंबा उत्तर थो हां है .. इसलिए संक्षिप्त उत्तर का प्रकार हां भी होना चाहिए।
बीटी

4
संक्षिप्त उत्तर है हाँ।
जेसन सी

जवाबों:


163

मुझे यकीन नहीं है कि अन्य उत्तर और टिप्पणियों का यहां क्या जिक्र है। यह आसानी से नहीं बल्कि संभव है। दो विकल्प हैं, जो दोनों को कम-संख्या वाले बंदरगाहों तक पहुंचने की अनुमति देते हैं, बिना प्रक्रिया को जड़ तक बढ़ाए:

विकल्प 1: CAP_NET_BIND_SERVICEएक प्रक्रिया में कम-संख्या वाले पोर्ट एक्सेस देने के लिए उपयोग करें:

इसके साथ आप setcapकमांड के माध्यम से कम संख्या वाले बंदरगाहों के लिए बाध्य करने के लिए एक विशिष्ट बाइनरी तक स्थायी पहुंच प्रदान कर सकते हैं :

sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary

ई / आई / पी भाग पर अधिक जानकारी के लिए, देखें cap_from_text

ऐसा करने के बाद, /path/to/binaryकम संख्या वाले बंदरगाहों के लिए बाध्य करने में सक्षम हो जाएगा। ध्यान दें कि आपको setcapबाइनरी पर सिम्लिंक के बजाय स्वयं का उपयोग करना होगा ।

विकल्प 2: authbindमहीन उपयोगकर्ता / समूह / बंदरगाह नियंत्रण के साथ एक बार पहुंच प्रदान करने के लिए उपयोग करें :

authbind( आदमी पेज ) उपकरण इस के लिए ठीक से मौजूद है।

  1. authbindअपने पसंदीदा पैकेज मैनेजर का उपयोग करके इंस्टॉल करें ।

  2. सभी उपयोगकर्ताओं और समूहों से 80 और 443 को अनुमति देने के लिए संबंधित बंदरगाहों तक पहुंच प्रदान करने के लिए इसे कॉन्फ़िगर करें:

    sudo touch /etc/authbind/byport/80
    sudo touch /etc/authbind/byport/443
    sudo chmod 777 /etc/authbind/byport/80
    sudo chmod 777 /etc/authbind/byport/443
    
  3. अब अपनी कमांड निष्पादित करें authbind(वैकल्पिक रूप से निर्दिष्ट --deepया अन्य तर्कों के साथ, मैन पेज देखें):

    authbind --deep /path/to/binary command line args
    

    उदाहरण के लिए

    authbind --deep java -jar SomeServer.jar
    

उपरोक्त दोनों के लिए अपसाइड और डाउनसाइड हैं। विकल्प 1 बाइनरी पर भरोसा करता है, लेकिन प्रति पोर्ट एक्सेस पर कोई नियंत्रण प्रदान नहीं करता है। विकल्प 2 उपयोगकर्ता / समूह पर भरोसा करता है और प्रति पोर्ट एक्सेस पर नियंत्रण प्रदान करता है लेकिन, AFAIK, केवल IPv4 का समर्थन करता है।


क्या वास्तव में rwxअनुमति की आवश्यकता है?
मैट

विकल्प 1 में ऑपरेशन वापस जाने के लिए, आप का उपयोग कर फिर से आदेश चला होगा -pकी intead +eip?
eugene1832

5
खबरदार, सेट के साथ, यदि आप निष्पादन योग्य को अधिलेखित कर देते हैं जिसे आप विशेषाधिकार प्रदान करते हैं (उदाहरण के लिए: एक पुनर्निर्माण करें) तो यह अपनी विशेषाधिकार प्राप्त पोर्ट स्थिति खो देता है और आपको इसे फिर से विशेषाधिकार देना होगा: |
रॉगरडपैक

1
कुछ ऐसा जो मुझे करना पड़ा; मैं एक sysv सेवा चलाने की कोशिश कर रहा था, जो कि एक रूबी निष्पादन योग्य है जो माणिक का उपयोग करता है। आपको संस्करणsetcap पर अनुमति देने की आवश्यकता/usr/bin/ruby1.9.1
क्रिश्चियन रोंडू

3
मुझे मेरा संदेह है कि chmod777 byportफाइलें आईएनजी सबसे अच्छा विचार है। मैं से लेकर permisions दे रही है देखा है 500करने के लिए 744। मैं आपके लिए काम करने वाले सबसे अधिक प्रतिबंधक से बचूंगा।
पेरे

28

डेल हागलगुंड पर हाजिर है। इसलिए मैं केवल एक ही बात कहने जा रहा हूं, लेकिन कुछ अलग तरीके से और कुछ उदाहरणों के साथ। ☺

यूनिक्स और लिनक्स दुनिया में करने के लिए सही चीज़ है:

  • एक छोटा, सरल, आसानी से सुनने योग्य कार्यक्रम, जो सुपरसुसर के रूप में चलता है और सुनने वाले सॉकेट को बांधता है;
  • एक और छोटा, सरल, आसानी से सुनने योग्य कार्यक्रम, जो विशेषाधिकारों को गिराता है, पहला कार्यक्रम
  • सेवा का मांस, एक अलग तीसरे कार्यक्रम में, एक गैर-सुपरसुअर खाते के तहत चलाया जाता है और दूसरे कार्यक्रम द्वारा लोड की गई श्रृंखला, सॉकेट के लिए बस एक खुली फाइल डिस्क्रिप्टर विरासत में मिलने की उम्मीद है।

आपके पास गलत विचार है कि उच्च जोखिम कहां है। उच्च जोखिम नेटवर्क से पढ़ने और एक सॉकेट खोलने, इसे एक बंदरगाह से बांधने, और कॉल करने के सरल कार्यों में नहीं पढ़ा जाने पर अभिनय करना हैlisten() । यह एक ऐसी सेवा का हिस्सा है जो वास्तविक संचार करता है जो उच्च जोखिम है। खुलने वाले हिस्से bind(), और listen(), और यहां तक ​​कि (एक हद तक) वह हिस्सा accepts(), जो उच्च जोखिम नहीं है और सुपरसुसर के तत्वावधान में चलाया जा सकता है। वे accept()नेटवर्क पर अविश्वसनीय अजनबियों के नियंत्रण में हैं डेटा पर ( मामले में स्रोत आईपी पते के अपवाद के साथ) उपयोग और कार्य नहीं करते हैं।

ऐसा करने के कई तरीके हैं।

inetd

जैसा कि डेल हाग्लगंड कहते हैं, पुराना "नेटवर्क सुपरसर्वर" inetdऐसा करता है। वह खाता जिसके तहत सेवा प्रक्रिया चलाई जाती है, वह कॉलम में से एक है inetd.conf। यह सुनने के भाग और छोड़ने वाले विशेषाधिकारों को दो अलग-अलग कार्यक्रमों में अलग नहीं करता है, छोटे और आसानी से सुनने योग्य, लेकिन यह मुख्य सेवा कोड को एक अलग कार्यक्रम में अलग करता है, exec()एक सेवा प्रक्रिया में एड जो एक खुली फ़ाइल विवरणक के साथ घूमता है सॉकेट के लिए।

ऑडिटिंग की कठिनाई इतनी अधिक समस्या नहीं है, क्योंकि किसी को केवल एक प्रोग्राम का ऑडिट करना होता है। inetdअधिक बड़ी समस्या ऑडिटिंग नहीं है, बल्कि यह है कि यह हाल के औजारों की तुलना में सिंपल फाइन ग्रेनड रनटाइम सर्विस कंट्रोल प्रदान नहीं करता है।

UCSPI-TCP और daemontools

डैनियल जे। बर्नस्टीन के UCSPI-TCP और daemontools संकुल को संयोजन के रूप में ऐसा करने के लिए डिज़ाइन किया गया था। वैकल्पिक रूप से ब्रूस Guenter के बड़े पैमाने पर समकक्ष डेमोनटूल-एनकोर टूलसेट का उपयोग कर सकते हैं ।

सॉकेट फ़ाइल डिस्क्रिप्टर को खोलने और विशेषाधिकार प्राप्त स्थानीय पोर्ट से बाइंड करने का कार्यक्रम tcpserverUCSPI-TCP से है। यह करता है listen()और दोनों accept()

tcpserverइसके बाद या तो एक सेवा कार्यक्रम शुरू होता है जो रूट विशेषाधिकारों को छोड़ देता है (क्योंकि परोसा जा रहा प्रोटोकॉल में सुपरसिर के रूप में शुरू करना शामिल है और फिर "लॉगिंग", जैसा कि मामला है, उदाहरण के लिए, एक एफ़टीपी या एक एसएसएच डेमॉन) या setuidgidजो है स्वयं निहित छोटे और आसानी से श्रव्य कार्यक्रम जो विशेष रूप से विशेषाधिकारों को छोड़ देता है और फिर श्रृंखला को सेवा कार्यक्रम में लोड करता है उचित (जिसका कोई हिस्सा कभी भी सुपरसुसर विशेषाधिकारों के साथ नहीं चलता, जैसा कि मामला है, कहते हैं qmail-smtpd)।

runइस प्रकार एक सेवा स्क्रिप्ट उदाहरण के लिए होगी (यह शून्य आईडी सेवा प्रदान करने के लिए डमीटिड के लिए एक है ):

#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl

nosh

मेरा nosh पैकेज ऐसा करने के लिए डिज़ाइन किया गया है। इसकी एक छोटी सी setuidgidउपयोगिता है, दूसरों की तरह। एक मामूली अंतर यह है कि यह systemd"LISTEN_FDS" सेवाओं के साथ-साथ UCSPI-TCP सेवाओं के साथ प्रयोग करने योग्य है , इसलिए पारंपरिक tcpserverकार्यक्रम को दो अलग-अलग कार्यक्रमों द्वारा प्रतिस्थापित किया जाता है: tcp-socket-listenऔर tcp-socket-accept

फिर से, एकल-उद्देश्य उपयोगिताओं स्पॉन और चेन एक दूसरे को लोड करते हैं। डिजाइन की एक दिलचस्प विचित्रता यह है कि सुपरसुसर विशेषाधिकारों को छोड़ सकते हैं, listen()लेकिन इससे पहले भी accept()। यहाँ एक runस्क्रिप्ट है qmail-smtpdजो वास्तव में ठीक वैसा ही करती है:

#!/bin/nosh
fdmove -c 2 1
clearenv --keep-path --keep-locale
envdir env/
softlimit -m 70000000
tcp-socket-listen --combine4and6 --backlog 2 ::0 smtp
setuidgid qmaild
sh -c 'exec \
tcp-socket-accept -v -l "${LOCAL:-0}" -c "${MAXSMTPD:-1}" \
ucspi-socket-rules-check \
qmail-smtpd \
'

प्रोग्राम हैं जो सुपर उपयोगकर्ता के तत्वावधान में चलाए जा छोटे सेवा-अज्ञेयवाद श्रृंखला लोडिंग उपकरण हैं fdmove, clearenv, envdir, softlimit, tcp-socket-listen, और setuidgidshप्रारंभ होने वाले बिंदु तक , सॉकेट smtpबंदरगाह के लिए खुला और बाध्य है , और इस प्रक्रिया में अब सुपरसुसर विशेषाधिकार नहीं हैं।

s6, s6- नेटवर्किंग, और निष्पादित करें

लॉरेंट Bercot के S6 और S6-नेटवर्किंग संकुल संयोजन के रूप में यह करने के लिए डिजाइन किए गए थे। आदेश संरचनात्मक रूप से daemontoolsऔर UCSPI-TCP के समान हैं।

runस्क्रिप्ट ज्यादा एक ही हो सकता है, के प्रतिस्थापन के अलावा s6-tcpserverके लिए tcpserverऔर s6-setuidgidके लिए setuidgid। हालाँकि, एक ही समय में एम। बरकोट के एक्सेललाइन टूलसेट का उपयोग करने का भी चयन किया जा सकता है ।

यहां एफ़टीपी सेवा का एक उदाहरण दिया गया है , जिसे वेन मार्शल के मूल से हल्के ढंग से संशोधित किया गया है , जो पब्लिकलाइन से एफ़लाइन, एस 6, एस 6-नेटवर्किंग और एफ़टीपी सर्वर प्रोग्राम का उपयोग करता है :

#!/command/execlineb -PW
multisubstitute {
    define CONLIMIT 41
    define FTP_ARCHIVE "/var/public/ftp"
}
fdmove -c 2 1
s6-envuidgid pubftp 
s6-softlimit -o25 -d250000 
s6-tcpserver -vDRH -l0 -b50 -c ${CONLIMIT} -B '220 Features: a p .' 0 21 
ftpd ${FTP_ARCHIVE}

ipsvd

गेरिट पपी का ipsvd एक और टूलसेट है जो ucspi-tcp और s6-नेटवर्किंग के समान लाइनों के साथ चलता है। उपकरण हैं chpstऔर tcpsvdइस बार, लेकिन वे एक ही काम करते हैं, और उच्च जोखिम कोड जो कि अविश्वसनीय ग्राहकों द्वारा नेटवर्क पर भेजे गए चीजों के पढ़ने, प्रसंस्करण और लेखन को करता है, अभी भी एक अलग कार्यक्रम में है।

यहां एम। पपी काfnord एक runस्क्रिप्ट में चलने का उदाहरण है :

#!/bin/sh
exec 2>&1
cd /public/10.0.5.4
exec \
chpst -m300000 -Uwwwuser \
tcpsvd -v 10.0.5.4 443 sslio -v -unobody -//etc/fnord/jail -C./cert.pem \
fnord

systemd

systemdनई सेवा पर्यवेक्षण और init प्रणाली जो कुछ लिनक्स वितरणों में पाई जा सकती है, का उद्देश्य है कि inetdवह क्या कर सकता है । हालांकि, यह छोटे स्व-निहित कार्यक्रमों के एक सूट का उपयोग नहीं करता है। systemdदुर्भाग्य से, इसकी संपूर्णता का लेखा- जोखा करना होगा।

systemdएक के साथ एक गर्तिका को परिभाषित करने के लिए विन्यास फाइल बनाता है systemd, और एक सेवा जो systemdशुरू होती है। सेवा "यूनिट" फ़ाइल में सेटिंग्स हैं जो सेवा प्रक्रिया पर नियंत्रण का एक बड़ा सौदा करने की अनुमति देती हैं, जिसमें वह किस उपयोगकर्ता के रूप में चलती है।

उस उपयोगकर्ता के साथ एक गैर-सुपरयुसर होने के लिए, systemdसॉकेट खोलने, उसे एक बंदरगाह पर बांधने, और कॉलिंग listen()(और, यदि आवश्यक हो, accept()) प्रक्रिया # 1 में सुपरयुसर के रूप में, और सेवा प्रक्रिया के सभी कार्य करता है spawns सुपरसुसर विशेषाधिकारों के बिना चलता है।


2
प्रशंसा के लिए धन्यवाद। यह ठोस सलाह का एक शानदार संग्रह है। +1।
डेल हाग्लगंड

11

मेरे पास एक अलग दृष्टिकोण है। मैं एक नोड.जेएस सर्वर के लिए पोर्ट 80 का उपयोग करना चाहता था। Node.js गैर-sudo उपयोगकर्ता के लिए स्थापित किए जाने के बाद से मैं इसे करने में असमर्थ था। मैंने सिमिलिंक का उपयोग करने की कोशिश की, लेकिन यह मेरे लिए काम नहीं किया।

तब मुझे पता चला कि मैं एक पोर्ट से दूसरे पोर्ट में कनेक्शन फॉरवर्ड कर सकता हूं। इसलिए मैंने सर्वर को पोर्ट 3000 पर शुरू किया और पोर्ट 80 से पोर्ट 3000 तक आगे पोर्ट सेट किया।

यह लिंक वास्तविक कमांड प्रदान करता है जिसका उपयोग यह करने के लिए किया जा सकता है। यहाँ आदेश हैं -

स्थानीय होस्ट / लूपबैक

sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 3000

बाहरी

sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000

मैंने दूसरी कमांड का उपयोग किया है और इसने मेरे लिए काम किया है। इसलिए मुझे लगता है कि यह उपयोगकर्ता-प्रक्रिया को सीधे निचले बंदरगाहों तक पहुंचने की अनुमति नहीं देने के लिए एक मध्यम आधार है, लेकिन पोर्ट-फ़ॉरवर्डिंग का उपयोग करके उन्हें एक्सेस प्रदान करता है।


6
+1 आउट ऑफ द बॉक्स सोचने के लिए
रिचर्ड वाइसमैन

4

आपकी प्रवृत्ति पूरी तरह से सही है: एक बड़े जटिल कार्यक्रम को जड़ के रूप में चलाना एक बुरा विचार है, क्योंकि उनकी जटिलता उन्हें विश्वास करना कठिन बनाती है।

लेकिन, नियमित उपयोगकर्ताओं को विशेषाधिकार प्राप्त बंदरगाहों से बांधने की अनुमति देना एक बुरा विचार है, क्योंकि ऐसे पोर्ट आमतौर पर महत्वपूर्ण सिस्टम सेवाओं का प्रतिनिधित्व करते हैं।

इस स्पष्ट विरोधाभास को हल करने के लिए मानक दृष्टिकोण विशेषाधिकार पृथक्करण है । मूल विचार आपके कार्यक्रम को दो (या अधिक) भागों में अलग करना है, जिनमें से प्रत्येक समग्र अनुप्रयोग का एक अच्छी तरह से परिभाषित टुकड़ा है, और जो सरल सीमित इंटरफेस द्वारा संवाद करता है।

आपके द्वारा दिए गए उदाहरण में, आप अपने प्रोग्राम को दो टुकड़ों में अलग करना चाहते हैं। एक जो रूट के रूप में चलता है और विशेषाधिकार प्राप्त सॉकेट से खुलता है और बांधता है, और फिर इसे किसी तरह से दूसरे हिस्से को सौंप देता है, जो एक नियमित उपयोगकर्ता के रूप में चलता है।

इस अलगाव को प्राप्त करने के लिए ये दो मुख्य तरीके हैं।

  1. एक एकल कार्यक्रम जो रूट के रूप में शुरू होता है। बहुत ही पहली बात यह आवश्यक सॉकेट बनाता है, जितना संभव हो उतना सरल और सीमित है। फिर, यह विशेषाधिकारों को छोड़ देता है, अर्थात, यह खुद को एक नियमित उपयोगकर्ता मोड प्रक्रिया में परिवर्तित करता है, और अन्य सभी कार्य करता है। सही तरीके से विशेषाधिकार छोड़ना मुश्किल है, इसलिए कृपया इसे करने के सही तरीके का अध्ययन करने के लिए समय निकालें।

  2. कार्यक्रमों की एक जोड़ी जो एक मूल प्रक्रिया द्वारा बनाई गई सॉकेट जोड़ी पर संवाद करती है। एक गैर-विशेषाधिकार प्राप्त ड्राइवर प्रोग्राम प्रारंभिक तर्क प्राप्त करता है और शायद कुछ बुनियादी तर्क सत्यापन करता है। यह सॉकेटपेयर () के माध्यम से जुड़े सॉकेट्स की जोड़ी बनाता है, और फिर दो अन्य कार्यक्रमों को कांटे और निष्पादित करता है जो वास्तविक काम करेंगे, और सॉकेट जोड़ी के माध्यम से संवाद करेंगे। इनमें से एक विशेषाधिकार प्राप्त है और सर्वर सॉकेट, और किसी भी अन्य विशेषाधिकार प्राप्त संचालन का निर्माण करेगा, और दूसरा अधिक जटिल और इसलिए कम विश्वसनीय अनुप्रयोग निष्पादन करेगा।

[१] http://en.m.wikipedia.org/wiki/Privilege_separation


आपके प्रपोज करने को सबसे अच्छा अभ्यास नहीं माना जाता है। आप एक ऐसे अशुभ को देख सकते हैं, जो एक विशेषाधिकार प्राप्त सॉकेट पर सुन सकता है और फिर उस अनपेक्षित कार्यक्रम के सॉकेट को हाथ लगा सकता है।
डेल हाग्लगंड

3

सरलतम समाधान: लिनक्स पर सभी विशेषाधिकार प्राप्त बंदरगाहों को हटा दें

उबंटू / डेबियन पर काम करता है:

#save configuration permanently
echo 'net.ipv4.ip_unprivileged_port_start=0' > /etc/sysctl.d/50-unprivileged-ports.conf
#apply conf
sysctl --system

(गैर रूट खाते के साथ वर्चुअलबॉक्स के लिए अच्छा काम करता है)

अब, सुरक्षा के बारे में सावधानी बरतें क्योंकि सभी उपयोगकर्ता सभी बंदरगाहों को बांध सकते हैं!


यह चालाकी है। एक छोटा नाइट: कॉन्फ़िगरेशन 80 और 443 खोलता है, लेकिन यह अन्य सभी पोर्ट भी खोलता है। अन्य बंदरगाहों पर आराम करने की अनुमति नहीं दी जा सकती है।
jww
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.