ฉันต้องการอนุญาตให้ผู้ใช้ (แตกต่างจากรูท) เพื่อเรียกใช้เซิร์ฟเวอร์ฟังบนพอร์ต 80
มีวิธีการทำเช่นนี้?
ฉันต้องการอนุญาตให้ผู้ใช้ (แตกต่างจากรูท) เพื่อเรียกใช้เซิร์ฟเวอร์ฟังบนพอร์ต 80
มีวิธีการทำเช่นนี้?
คำตอบ:
setcap 'cap_net_bind_service=+ep' /path/to/program
สิ่งนี้จะทำงานสำหรับกระบวนการเฉพาะ แต่เพื่อให้ผู้ใช้รายใดรายหนึ่งเชื่อมโยงกับพอร์ตที่ต่ำกว่า 1024 คุณจะต้องเพิ่มเขาใน sudoers
ดูที่การสนทนานี้มากขึ้น
(วิธีการเหล่านี้บางส่วนได้รับการกล่าวถึงในคำตอบอื่น ๆ ; ฉันให้ตัวเลือกที่เป็นไปได้หลายอย่างตามลำดับที่ต้องการ)
คุณสามารถเปลี่ยนเส้นทางพอร์ตต่ำไปยังพอร์ตสูงและฟังพอร์ตสูง
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
-A INPUT -p tcp --dport 1080 -j ACCEPT
มิฉะนั้นมันจะไม่ทำงาน (ฉันมี-j DROP
catch-all ด้วย) ดังนั้นฉันจึงเหลือซ็อคเก็ตการฟังสองตัวไว้
คำตอบสั้น ๆ คือไม่สามารถทำได้โดยการออกแบบ
คำตอบยาว ๆ คือในโลกโอเพนซอร์สมีผู้คนมากมายที่เล่นกับการออกแบบและหาวิธีอื่น โดยทั่วไปแล้วเป็นที่ยอมรับกันโดยทั่วไปว่าสิ่งนี้ไม่ควรทำ ความจริงที่ว่าคุณกำลังพยายามอาจหมายความว่าคุณมีความผิดพลาดในการออกแบบอื่นในระบบของคุณและควรพิจารณาสถาปัตยกรรมระบบทั้งหมดของคุณโดยคำนึงถึงแนวทางปฏิบัติที่ดีที่สุดและการรักษาความปลอดภัย
ที่กล่าวว่าหนึ่งในโปรแกรมสำหรับการเข้าถึงอำนาจที่ไม่ใช่รากไปยังท่าเรือต่ำauthbind ทั้งselinuxและgrsecurityยังมีเฟรมเวิร์กสำหรับการรับรองความถูกต้องแบบละเอียด
สุดท้ายถ้าคุณต้องการให้ผู้ใช้เฉพาะเรียกใช้โปรแกรมเฉพาะในฐานะรูทและสิ่งที่คุณต้องการจริงๆคือเพียงให้ผู้ใช้รีสตาร์ท apache หรืออะไรทำนองนั้นsudo
เป็นเพื่อนของคุณ!
คุณสามารถใช้การส่งต่อพอร์ตnetcat หรือ xinetdหรือ iptables หรือใช้ apache เป็นพร็อกซีส่วนหน้าและเรียกใช้กระบวนการบนพอร์ตที่ไม่มีสิทธิพิเศษ
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
และดำเนินการจนสุดความลึกที่เล็กที่สุดที่ใช้งานและใช้งานได้
ฉันลองใช้วิธี iptables PREROUTING REDIRECT แต่พบว่ามันมีผลกับแพ็คเก็ตที่ส่งต่อด้วย นั่นคือหากเครื่องกำลังส่งต่อแพ็กเก็ตระหว่างอินเทอร์เฟซ (เช่นหากทำหน้าที่เป็นจุดเชื่อมต่อ Wi-Fi ที่เชื่อมต่อกับเครือข่ายอีเธอร์เน็ต) กฎ iptables จะจับการเชื่อมต่อของลูกค้าที่เชื่อมต่อกับอินเทอร์เน็ตปลายทาง เครื่องจักร. นั่นไม่ใช่สิ่งที่ฉันต้องการ - ฉันเพียงต้องการเปลี่ยนเส้นทางการเชื่อมต่อที่ส่งไปยังเครื่องเท่านั้น
ความเป็นไปได้อย่างหนึ่งคือใช้การส่งต่อพอร์ต TCP เช่นใช้socat
:
socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080
อย่างไรก็ตามข้อเสียอย่างหนึ่งของวิธีการนี้คือแอปพลิเคชั่นที่รับฟังพอร์ต 8080 นั้นไม่ทราบที่อยู่ต้นทางของการเชื่อมต่อขาเข้า (เช่นการบันทึกหรือวัตถุประสงค์ในการระบุตัวตนอื่น ๆ )