سؤال هل تريد السماح بربط العملية غير الجذر بالمنفذ 80 و 443؟


هل من الممكن ضبط معلمة kernel للسماح لبرنامج userland بالربط بالمنفذ 80 و 443؟

السبب الذي أسأله هو أنني أعتقد أنه من الحماقة السماح لعملية مميزة لفتح مقبس والاستماع. أي شيء يفتح المقبس ويستمع هو خطر كبير ، ويجب ألا يتم تشغيل التطبيقات عالية المخاطر كجذر.

سأحاول بدلاً من ذلك معرفة ما هي العملية غير المحظوظة التي تستمع إلى المنفذ 80 بدلاً من محاولة إزالة البرامج الضارة التي اخترقت بامتيازات الجذر.


74
2018-02-02 05:48


الأصل


نرى serverfault.com/questions/268099 و stackoverflow.com/questions/413807 . الجواب القصير هو لا. - Sami Laine
الجواب الطويل هو نعم .. لذا يجب أن يكون الجواب القصير بنعم أيضًا. - B T
الجواب القصير هو نعم فعلا. - Jason C


الأجوبة:


لست متأكدًا مما تشير إليه الإجابات والتعليقات الأخرى هنا. هذا ممكن بسهولة. هناك خياران ، كلاهما يسمح بالوصول إلى المنافذ ذات الأرقام المنخفضة دون الحاجة إلى رفع العملية إلى الجذر:

الخيار 1: الاستخدام CAP_NET_BIND_SERVICE لمنح وصول منفذ ذو أرقام منخفضة إلى عملية:

مع هذا يمكنك منح الوصول الدائم إلى ثنائي معين لربط المنافذ ذات الأرقام المنخفضة عبر setcap أمر:

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

لمزيد من التفاصيل حول جزء e / i / p ، راجع 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 فقط.


110
2018-03-21 21:12



شكرا جاسون. يبدو أن هذا هو أفضل إجابة على السؤال ، ولكنه جاء متأخراً قليلاً. عذرا لعدم رؤيته في وقت مبكر. - jww
شكرا مرة اخرى على كل المعلومات. أعتقد أن هذا السؤال وسؤال المستخدم سوبر يتفوق على snot من إجابات خطأ خادم. والناس على Super User أكثر ودية ودود. - jww
كن حذرا ، مع setcap ، إذا قمت بالكتابة فوق الملف التنفيذي ، فإنك تمنح الامتيازات (مثلا: قم بإعادة البناء) ، ثم تفقد حالة المنفذ المميز الخاص بها ، ويجب عليك منحها امتيازات مرة أخرى: | - rogerdpack
شيء كان عليّ أن أعمل معه كنت أحاول تشغيل خدمة sysv ، التي تدير روبي قابل للتنفيذ يستخدم روبي. تحتاج إلى إعطاء setcap إذن على نسخة محددة روبي للتنفيذعلى سبيل المثال /usr/bin/ruby1.9.1 - Christian Rondeau
لدي شكوكي ذلك chmodجي إلى 777 byport الملفات هي أفضل فكرة. لقد رأيت منح تراخيص تتراوح من 500 إلى 744. كنت ألصق بواحد أكثر تقييدا ​​بالنسبة لك. - Pere


ديل Hagglund على الفور. لذلك سأقول نفس الشيء ولكن بطريقة مختلفة ، مع بعض التفاصيل والأمثلة. ☺

الشيء الصحيح الذي يجب فعله في عالم يونكس ولينكس هو:

  • الحصول على برنامج صغير ، بسيط ، يمكن تدقيقه بسهولة ، يعمل كمستخدم متميز ، ويربط مأخذ الاستماع ؛
  • الحصول على برنامج آخر صغير وبسيط وقابل للتدقيق بسهولة ، يسقط الامتيازات ، وينتج عن البرنامج الأول ؛
  • للحصول على لحم الخدمة ، في مكان منفصل الثالث البرنامج ، تحت حساب غير متسلسلاً وسلسلة محملة بالبرنامج الثاني ، متوقعًا ببساطة أن يرث واصفًا مفتوحًا للمقبس.

لديك فكرة خاطئة عن مكان الخطر المرتفع. الخطر الكبير في القراءة من الشبكة والتصرف بناء على ما يقرأ ليس في أعمال بسيطة من فتح مأخذ ، ملزمة لمنفذ ، والدعوة listen(). إنه جزء من الخدمة التي تجعل التواصل الفعلي هو الخطر الأكبر. الأجزاء التي تفتح ، bind()و listen()، وحتى (إلى حد) الجزء الذي accepts()، ليست عالية المخاطر ويمكن تشغيلها تحت رعاية the superuser. انهم لا يستخدمون ويتصرفون (باستثناء عناوين IP المصدر في accept() الحالة) البيانات التي تقع تحت سيطرة الغرباء غير الموثوقين عبر الشبكة.

هناك العديد من الطرق للقيام بذلك.

inetd

كما يقول ديل هاجلوند ، "شبكة فائقة superserver" القديمة inetd هل هذا. الحساب الذي يتم تشغيل عملية الخدمة به هو أحد الأعمدة في inetd.conf. لا يفصل جزء الاستماع وامتيازات التخفيض جزءًا في برنامجين منفصلين ، صغيران ويمكن تدقيقهما بسهولة ، ولكنه يفصل رمز الخدمة الرئيسي إلى برنامج منفصل ، exec()إد في عملية خدمة أنها spawns مع واصف ملف مفتوح للمقبس.

إن صعوبة المراجعة ليست مشكلة كبيرة ، حيث أن المرء لا يستطيع سوى تدقيق البرنامج الواحد. inetdالمشكلة الرئيسية ليست تدقيقًا كبيرًا ، ولكنها بالأحرى لا توفر تحكمًا بسيطًا في خدمة وقت التشغيل ، مقارنة بالأدوات الحديثة.

UCSPI-TCP و daemontools

دانيال ج. بيرنشتاين UCSPI-TCP و daemontools تم تصميم الحزم للقيام بذلك بالتزامن. يمكن للمرء بدلا من ذلك استخدام بروس Guenter في ما يعادل إلى حد كبير daemontools-وسيم مجموعة أدوات.

البرنامج لفتح واصف ملف مأخذ التوصيل والربط إلى المنفذ المحلي المميز هو tcpserverمن UCSPI-TCP. يفعل كلا listen() و ال accept().

tcpserver ثم ينتج عن ذلك برنامج خدمة يقوم بإسقاط امتيازات الجذر نفسها (لأن البروتوكول الذي يتم تقديمه يتضمن بدء كمستخدم ممتاز ثم "تسجيل الدخول" ، كما هو الحال مع ، على سبيل المثال ، بروتوكول نقل الملفات أو خادم SSH) أو setuidgid وهو عبارة عن برنامج صغير قابل للتسجيل ويمكن تدقيقه بسهولة ويسر حصريًا الامتيازات ثم يسلسل الأحمال إلى برنامج الخدمة الصحيح (لا يوجد أي جزء منه يتم تشغيله مع امتيازات مستخدم متميز ، كما هو الحال مع ، على سبيل المثال ، qmail-smtpd).

خدمة run النصي سيكون هكذا على سبيل المثال (هذا واحد ل dummyidentd لتوفير خدمة IDENT فارغة):

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

نوش

حزمة بلدي تم تصميمه للقيام بذلك. لديها صغيرة 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 \
'

البرامج التي تعمل تحت رعاية the superuser هي أدوات تحميل سلسلة لا أجري الخدمة الصغيرة fdmove، clearenv، envdir، softlimit، tcp-socket-listenو setuidgid. بنقطة ذلك sh بدأ ، ومقبس مفتوح ومربوطة إلى smtp المنفذ ، ولم تعد هذه العملية تتمتع بامتيازات مستخدم متميز.

s6 و s6-networking و execline

لوران بيركوت S6 و S6-الشبكات تم تصميم الحزم للقيام بذلك بالتزامن. الأوامر هي مشابهة جدا من الناحية الهيكلية لتلك daemontools و UCSPI-TCP.

run سوف تكون مخطوطات نفسها كثيرا ، باستثناء استبدال s6-tcpserver إلى عن على tcpserver و s6-setuidgid إلى عن على setuidgid. ومع ذلك ، يمكن للمرء أيضًا أن يختار استخدام M. Bercot execline مجموعة أدوات في نفس الوقت.

إليك مثال على خدمة FTP ، تم تعديلها بشكل خفيف من وين مارشال الأصليالتي تستخدم execline و s6 و s6-networking وبرنامج خادم FTP من publicfile:

#!/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-networking. الأدوات هي chpst و tcpsvd هذه المرة ، لكنهم يفعلون الشيء نفسه ، وشفرة المخاطرة العالية التي تقوم بقراءة ومعالجة وكتابة الأشياء المرسلة عبر الشبكة من قبل عملاء غير موثوقين ما زالت في برنامج منفصل.

من هنا مثال M. Pape من الجري 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 الذي يمكن العثور عليه في بعض توزيعات Linux ، يهدف إلى فعل ما inetd يمكن القيام به. ومع ذلك ، فإنه لا يستخدم مجموعة من البرامج الصغيرة المستقلة. على المرء أن يدقق systemd في مجمله ، لسوء الحظ.

مع systemd واحد يخلق ملفات التكوين لتحديد مأخذ التوصيل ذلك systemd يستمع ، والخدمة التي systemd يبدأ. يحتوي ملف "وحدة" الخدمة على إعدادات تسمح لأحدًا بتحكم كبير في عملية الخدمة ، بما في ذلك المستخدم الذي يشغله.

مع تعيين هذا المستخدم ليكون غير متميز ، systemd يفعل كل عمل فتح المقبس ، ملزمة له إلى الميناء ، والدعوة listen() (وإذا لزم الأمر ، accept()) في العملية رقم 1 باعتباره المستخدم المتميز ، وتعمل عملية الخدمة التي يتم إنتاجها بدون امتيازات المستخدم المتميز.


22
2018-02-02 16:21



شكرا للمجاملة. هذه مجموعة رائعة من النصائح الملموسة. +1. - Dale Hagglund
ليس هذا ليس نصيحة عامة كبيرة ، ولكن CAP_NET_BIND_SERVICE و authbind كلاهما موجودان لهذا الغرض ؛ للسماح للتطبيقات غير الجذر بالوصول إلى المنافذ ذات الأرقام المنخفضة. - Jason C
شكرا مرة اخرى على كل المعلومات. أعتقد أن هذا السؤال وسؤال المستخدم سوبر يتفوق على snot من إجابات خطأ خادم. والناس على Super User أكثر ودية ودود. - jww


غرائزك صحيحة تمامًا: إنها فكرة سيئة أن يتم تشغيل برنامج كبير معقد كجذر ، لأن تعقيدها يجعلها صعبة الثقة.

ولكن ، من المستحسن أيضًا السماح للمستخدمين المنتظمين بالالتزام بالمنافذ المميزة ، لأن هذه المنافذ تمثل عادةً خدمات نظام مهمة.

النهج القياسي لحل هذا التناقض الظاهري هو فصل الامتياز. الفكرة الأساسية هي فصل برنامجك إلى جزأين (أو أكثر) ، كل جزء منها يحتوي على جزء محدد من التطبيق العام ، ويتواصل عن طريق واجهات محدودة بسيطة.

في المثال الذي تقدمه ، تريد فصل برنامجك إلى قسمين. واحد يعمل كجذر ويفتح ويربط بالمقبس المميز ، ثم يسلمه بطريقة ما إلى الجزء الآخر ، والذي يعمل كمستخدم عادي.

هذان طريقتان رئيسيتان لتحقيق هذا الفصل.

  1. برنامج واحد يبدأ كجذر. أول شيء يفعله هو إنشاء المقبس الضروري ، بطريقة بسيطة ومحدودة قدر الإمكان. ثم ، فإنه يسقط الامتيازات ، أي أنه يحول نفسه إلى عملية وضع المستخدم العادي ، ويقوم بجميع الأعمال الأخرى. إسقاط الامتيازات بشكل صحيح أمر صعب ، لذا يرجى أخذ الوقت الكافي لدراسة الطريقة الصحيحة للقيام بذلك.

  2. زوج من البرامج التي تتصل عبر زوج مأخذ تم إنشاؤه بواسطة عملية الأصل. يتلقى برنامج تشغيل غير امتيازات الوسائط الأولية وربما بعض التحقق من الوسيطة الأساسية. أنه يخلق زوج من مآخذ توصيل متصلة عبر socketpair () ، ثم الشوك وتنفيد اثنين من البرامج الأخرى التي ستقوم بعمل حقيقي ، والتواصل عبر زوج المقبس. أحد هذه الميزات مميز وسيقوم بإنشاء مأخذ توصيل الملقم وأي عمليات أخرى مميزة ، وسيقوم الآخر بتنفيذ عملية تنفيذ أكثر تعقيدًا وبالتالي أقل موثوقية.

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


4
2018-02-02 06:49



شكرا دايل. لقد جئت من عالم Windows مع تجربة دورة حياة SDLC قوية ، لذلك أفهم ما تقوله. أنا لا أريد القيام به (1) بسبب ارتفاع مخاطره. بالإضافة إلى ذلك ، فوضى للقيام بذلك بشكل صحيح في جميع الظروف (أي ، Setuid dystystified). لا أريد القيام به (2) لأنه يضيف التعقيد. أريد فقط السماح لمستخدم غير منسب بالربط بالمنفذ 80 و 443. هذه هي الطريقة الأسلم والأسهل للقيام بذلك. - jww
ما هو الاقتراح الخاص بك لا يعتبر أفضل الممارسات. قد تنظر إلى inetd ، الذي يمكنه الاستماع إلى مقبس مميز ثم تسليم مأخذ التوصيل إلى برنامج غير محظور. - Dale Hagglund
شكرا مرة اخرى على كل المعلومات. أعتقد أن هذا السؤال وسؤال المستخدم سوبر يتفوق على snot من إجابات خطأ خادم. والناس على Super User أكثر ودية ودود. - jww


لدي نهج مختلف نوعا ما. كنت أرغب في استخدام المنفذ 80 لخادم node.js. لم أتمكن من القيام بذلك منذ تم تثبيت Node.js لمستخدم غير sudo. حاولت استخدام symlinks ، لكنه لم يعمل بالنسبة لي.

ثم تعرفت على أنه يمكنني إعادة توجيه الاتصالات من منفذ واحد إلى منفذ آخر. لذلك بدأت تشغيل الخادم على المنفذ 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

لقد استخدمت الأمر الثاني وعملت لي. ﻟذﻟك أﻋﺗﻘد أن ھذا ھو اﻷﺳﺎس اﻟﻣﺗوﺳط ﻟﻌدم اﻟﺳﻣﺎح ﻟﻌﻣﻟﯾﺔ اﻟﻣﺳﺗﺧدم ﺑﺎﻟوﺻول إﻟﯽ اﻟﻣﻧﺎﻓذ اﻷدﻧﯽ ﻣﺑﺎﺷرة ، وﻟﮐن ﻣﻧﺣﮭﺎ اﻟوﺻول ﺑﺎﺳﺗﺧدام ﺗوﺟﯾﮫ اﻟﻣوﻗﻊ


1
2018-06-27 07:00



+1 للتفكير خارج الصندوق - Richard Wiseman