การอนุญาตให้ผู้ใช้ปล่อยให้ฟังพอร์ตต่ำกว่า 1024


63

ฉันต้องการอนุญาตให้ผู้ใช้ (แตกต่างจากรูท) เพื่อเรียกใช้เซิร์ฟเวอร์ฟังบนพอร์ต 80

มีวิธีการทำเช่นนี้?


1
คำถามนี้เปิดให้ตีความ ฉันหวังว่าคุณหมายถึง "คุณได้สร้างบริการระบบใหม่ที่คุณ (ในฐานะที่เป็น root) ต้องการที่จะทำงานในบัญชีที่ไม่มีสิทธิพิเศษด้วยเหตุผลด้านความปลอดภัย" (ถือว่าเป็นวิธีปฏิบัติที่ดี) และไม่ใช่ "ฉันมีผู้ใช้ที่ถามว่า ใช้งานเว็บเซิร์ฟเวอร์ของตัวเองในระบบของฉันฉันจะอนุญาตให้พวกเขาเข้าถึงได้อย่างไร " (ถือว่าเป็นการฝึกที่ค่อนข้างแย่)
Michael Shaw

3
@Polemmy เหตุผลที่แท้จริงคือ: เครื่องของฉันอยู่หลังไฟร์วอลล์ที่ปิดกั้นพอร์ตใด ๆ แต่ 80 ฉันต้องการโฮสต์เซิร์ฟเวอร์ (ซึ่งไม่ได้ลดสิทธิ์!) ดังนั้นจึงต้องฟังจากพอร์ต 80 แต่ไม่ต้องสวม ไม่ไว้ใจให้รันในฐานะรูท (เพื่อเหตุผลด้านความปลอดภัยที่ชัดเจน) ฉันได้รับอนุญาตให้ทำเช่นนี้ถ้าคุณเป็นห่วง
peoro

คำตอบ:


50

setcap 'cap_net_bind_service=+ep' /path/to/program

สิ่งนี้จะทำงานสำหรับกระบวนการเฉพาะ แต่เพื่อให้ผู้ใช้รายใดรายหนึ่งเชื่อมโยงกับพอร์ตที่ต่ำกว่า 1024 คุณจะต้องเพิ่มเขาใน sudoers

ดูที่การสนทนานี้มากขึ้น


31

(วิธีการเหล่านี้บางส่วนได้รับการกล่าวถึงในคำตอบอื่น ๆ ; ฉันให้ตัวเลือกที่เป็นไปได้หลายอย่างตามลำดับที่ต้องการ)

คุณสามารถเปลี่ยนเส้นทางพอร์ตต่ำไปยังพอร์ตสูงและฟังพอร์ตสูง

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080

คุณสามารถเริ่มต้นเซิร์ฟเวอร์ของคุณในฐานะสิทธิ์การใช้งานรูทและดรอปหลังจากที่เริ่มฟังบนพอร์ตที่มีสิทธิ์ โดยเฉพาะอย่างยิ่งแทนที่จะเขียนโค้ดด้วยตัวคุณเองให้เริ่มเซิร์ฟเวอร์ของคุณจาก wrapper ที่ทำงานให้คุณ หากเซิร์ฟเวอร์ของคุณเริ่มต้นหนึ่งอินสแตนซ์ต่อการเชื่อมต่อให้เริ่มจากinetd(หรือโปรแกรมที่คล้ายกันเช่นxinetd) สำหรับinetdใช้บรรทัดเช่นนี้ใน/etc/inetd.conf:

http  stream  tcp  nowait  username:groupname  /path/to/server/executable  argv[0] argv[1]…

authbindหากเซิร์ฟเวอร์ของคุณฟังในเช่นเดียวเริ่มต้นได้จากโปรแกรมเช่น สร้างไฟล์ที่ว่างเปล่า/etc/authbind/byport/80และทำให้สามารถเรียกใช้กับผู้ใช้ที่รันเซิร์ฟเวอร์ หรือสร้าง/etc/authbind/byuid/1234ที่ 1234 เป็น UID 0.0.0.0/0:80,80ใช้เซิร์ฟเวอร์ที่มีเส้น

หากความสามารถในการปฏิบัติการของเซิร์ฟเวอร์ของคุณถูกเก็บไว้ในระบบไฟล์ที่รองรับความสามารถคุณสามารถกำหนดความสามารถดังกล่าวได้ ระวังว่ามีความสามารถยังค่อนข้างใหม่และยังคงมีข้อบกพร่องไม่กี่cap_net_bind_service

setcap cap_net_bind_service=ep /path/to/server/executable

4
ในทุกกรณีที่ฉันต้องจัดการกับมันปฏิบัติการเป็นสคริปต์ที่เปิดตัวจาวาหรืองูใหญ่ ในฐานะที่เป็นผู้ชายที่ใช้เวลาไม่ถึง 10 ชั่วโมงในการปรับคะแนนโซลูชั่น iptables ของคุณครอบคลุมอย่างเจ็บปวด
srking

สำหรับโซลูชัน iptables ฉันต้องเพิ่มกฎตัวกรองเช่น-A INPUT -p tcp --dport 1080 -j ACCEPTมิฉะนั้นมันจะไม่ทำงาน (ฉันมี-j DROPcatch-all ด้วย) ดังนั้นฉันจึงเหลือซ็อคเก็ตการฟังสองตัวไว้
thom_nic

4

คำตอบสั้น ๆ คือไม่สามารถทำได้โดยการออกแบบ

คำตอบยาว ๆ คือในโลกโอเพนซอร์สมีผู้คนมากมายที่เล่นกับการออกแบบและหาวิธีอื่น โดยทั่วไปแล้วเป็นที่ยอมรับกันโดยทั่วไปว่าสิ่งนี้ไม่ควรทำ ความจริงที่ว่าคุณกำลังพยายามอาจหมายความว่าคุณมีความผิดพลาดในการออกแบบอื่นในระบบของคุณและควรพิจารณาสถาปัตยกรรมระบบทั้งหมดของคุณโดยคำนึงถึงแนวทางปฏิบัติที่ดีที่สุดและการรักษาความปลอดภัย

ที่กล่าวว่าหนึ่งในโปรแกรมสำหรับการเข้าถึงอำนาจที่ไม่ใช่รากไปยังท่าเรือต่ำauthbind ทั้งselinuxและgrsecurityยังมีเฟรมเวิร์กสำหรับการรับรองความถูกต้องแบบละเอียด

สุดท้ายถ้าคุณต้องการให้ผู้ใช้เฉพาะเรียกใช้โปรแกรมเฉพาะในฐานะรูทและสิ่งที่คุณต้องการจริงๆคือเพียงให้ผู้ใช้รีสตาร์ท apache หรืออะไรทำนองนั้นsudoเป็นเพื่อนของคุณ!


8
พอร์ต "ความปลอดภัย" ไม่ได้ให้อะไรคุณมากนักในโลกสมัยใหม่
pjc50

3
@ pjc50: ใช่แล้ว มันเกี่ยวกับความไว้วางใจโดยนัย หมายเลขพอร์ตต่ำแสดงถึงความน่าเชื่อถือสูง SSH, POP, FTP และ daemons อื่น ๆ คาดว่าจะขอรหัสผ่านระดับระบบและข้อมูลประจำตัวอื่น ๆ เมื่อเปิดพอร์ตของพวกเขา หากผู้ใช้ได้รับอนุญาตให้ฟังพอร์ตต่ำบนกล่องพวกเขาสามารถเริ่มต้น phony daemons บนพอร์ตที่ไม่ได้ใช้งาน (หรือล้มเหลว) และเก็บเกี่ยวรหัสผ่านจากผู้ใช้ที่ไม่สงสัย รหัสผ่านเหล่านั้นสามารถใช้ในช่องนั้นเพื่อประนีประนอมบัญชีอื่นรวมถึงรูท
แม็กเคเล็บ

8
นั่นเป็นรูปแบบความปลอดภัยที่ค่อนข้างอ่อนแอ หากคุณเชื่อมต่อกับบางสิ่งบางอย่างและไม่ทำธุรกรรมใบรับรองคุณไม่ทราบว่าคุณกำลังพูดถึงใคร - นั่นคือการโจมตีของ MITM
pjc50

5
ฉันคิดว่าสิ่งที่จำเป็นคือ chown สำหรับพอร์ต: จากนั้นคุณสามารถ "chown mail port25" จากนั้น (a) daemon จดหมายของคุณไม่จำเป็นต้องเริ่มต้นด้วย root privs และ (b) ไม่มีใครสามารถขโมยมันได้
pjc50

7
ขณะนี้อาจเป็นจริง "โดยการออกแบบ" เมื่อ linux อยู่ในวัยเด็กของมันทำให้รู้สึกน้อยมากแล้วและตอนนี้ ความปลอดภัยคือทั้งหมดที่ผู้ใช้สามารถทำได้และไม่สามารถทำได้ ยกตัวอย่างเช่นการอนุญาตให้ผู้ใช้รูทใช้พอร์ต 80 เท่านั้นเป็นความเสี่ยงด้านความปลอดภัยขนาดใหญ่เนื่องจากหมายความว่าคุณต้องให้สิทธิ์การเข้าถึงรูทแก่ผู้ที่ต้องใช้พอร์ต 80 แต่ไม่ควรมีสิทธิ์เข้าถึงรูท หากคุณเชื่อถือผู้ใช้ที่ไม่ใช่รูท X เพื่อใช้พอร์ต 80 คุณควรสามารถเข้ารหัสที่ไว้วางใจในระบบปฏิบัติการของคุณ โชคดีที่คุณพูดถึงมีงานเส็งเคร็งที่อนุญาตนี้เช่น authbind
BT

3

คุณสามารถใช้การส่งต่อพอร์ตnetcat หรือ xinetdหรือ iptables หรือใช้ apache เป็นพร็อกซีส่วนหน้าและเรียกใช้กระบวนการบนพอร์ตที่ไม่มีสิทธิพิเศษ


3

Authbind , @Gilles พูดถึงมันแล้ว แต่ฉันต้องการขยายออกไปเล็กน้อย

มันมีการควบคุมการเข้าถึงที่สะดวก (รายละเอียดในหน้าคน): คุณสามารถกรองการเข้าถึงโดยพอร์ตที่อยู่อินเตอร์เฟซ uid ช่วงที่อยู่หรือพอร์ตและการรวมกันของเหล่านี้

มันมีพารามิเตอร์ที่มีประโยชน์มาก--depth:

- ระดับความลึก

ทำให้ authbind ส่งผลกระทบต่อโปรแกรมที่อยู่ในระดับลึกลงไปในกราฟการโทร ค่าเริ่มต้นคือ 1

"ระดับลึก" หมายถึงเมื่อสคริปต์ (หรือโปรแกรม) เรียกใช้สคริปต์อื่นที่ลงมาในระดับหนึ่ง ดังนั้นถ้าคุณมีความ--depth 5หมายในระดับ 1 (หรือเป็น 0?) ถึง 5 คุณมีสิทธิ์ผูกในขณะที่ในระดับ 6 และต่อไปคุณจะไม่ทำ มีประโยชน์เมื่อคุณต้องการให้สคริปต์เข้าถึง แต่ไม่ใช่โปรแกรมที่ทำงานโดยมีหรือไม่มีความรู้ของคุณ


เพื่อแสดงให้เห็นว่าคุณอาจมีสิ่งนี้: เพื่อความปลอดภัยคุณมีผู้ใช้javaที่ตั้งใจจะเรียกใช้จาวาเท่านั้นและคุณต้องการให้เขาเข้าถึงพอร์ต 80:

echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80

ฉันได้สร้าง../byport/80 fileมอบให้กับjavaกลุ่มผู้ใช้ (ผู้ใช้แต่ละคนมีกลุ่มของตัวเอง) และทำให้มันสามารถเรียกใช้งานได้ตามกลุ่มซึ่งหมายความว่าสามารถเรียกjavaใช้งานได้โดยผู้ใช้ หากคุณให้การเข้าถึงโดยพอร์ตไฟล์จะต้องสามารถเรียกใช้งานได้โดยผู้ใช้ที่ควรมีสิทธิ์เข้าถึงดังนั้นเราจึงทำเช่นนั้น

สิ่งนี้อาจเพียงพอสำหรับค่าเฉลี่ย Joe แต่เนื่องจากคุณรู้วิธีใช้--depthพารามิเตอร์คุณจึงเรียกใช้ (ในฐานะjavaผู้ใช้) authbind --depth [depth] my_web_app's_start_scriptเริ่มต้น--depth 1และดำเนินการจนสุดความลึกที่เล็กที่สุดที่ใช้งานและใช้งานได้

อ่านหน้าคนสำหรับรายละเอียด


1

ฉันลองใช้วิธี iptables PREROUTING REDIRECT แต่พบว่ามันมีผลกับแพ็คเก็ตที่ส่งต่อด้วย นั่นคือหากเครื่องกำลังส่งต่อแพ็กเก็ตระหว่างอินเทอร์เฟซ (เช่นหากทำหน้าที่เป็นจุดเชื่อมต่อ Wi-Fi ที่เชื่อมต่อกับเครือข่ายอีเธอร์เน็ต) กฎ iptables จะจับการเชื่อมต่อของลูกค้าที่เชื่อมต่อกับอินเทอร์เน็ตปลายทาง เครื่องจักร. นั่นไม่ใช่สิ่งที่ฉันต้องการ - ฉันเพียงต้องการเปลี่ยนเส้นทางการเชื่อมต่อที่ส่งไปยังเครื่องเท่านั้น

ความเป็นไปได้อย่างหนึ่งคือใช้การส่งต่อพอร์ต TCP เช่นใช้socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

อย่างไรก็ตามข้อเสียอย่างหนึ่งของวิธีการนี้คือแอปพลิเคชั่นที่รับฟังพอร์ต 8080 นั้นไม่ทราบที่อยู่ต้นทางของการเชื่อมต่อขาเข้า (เช่นการบันทึกหรือวัตถุประสงค์ในการระบุตัวตนอื่น ๆ )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.