Dale Hagglund เป็นจุดบน ดังนั้นฉันจะพูดในสิ่งเดียวกัน แต่ในวิธีที่แตกต่างกันโดยเฉพาะและตัวอย่าง ☺
สิ่งที่ควรทำใน Unix และ Linux ในโลกคือ:
- มีขนาดเล็กง่ายตรวจสอบได้ง่ายโปรแกรมที่ทำงานเป็น superuser และผูกซ็อกเก็ตการฟัง
- การมีโปรแกรมขนาดเล็กง่ายตรวจสอบได้ง่ายซึ่งลดสิทธิพิเศษเกิดจากโปรแกรมแรก
- ในการรับเนื้อของบริการในโปรแกรมที่สามแยกต่างหากทำงานภายใต้บัญชีที่ไม่ใช่ superuser และเชนที่โหลดโดยโปรแกรมที่สองคาดว่าจะรับสืบทอด descriptor เปิดไฟล์สำหรับซ็อกเก็ต
คุณมีความคิดผิด ๆ ว่าที่ใดมีความเสี่ยงสูง มีความเสี่ยงสูงอยู่ในการอ่านจากเครือข่ายและการปฏิบัติตามสิ่งที่อ่านlisten()
ไม่ได้อยู่ในการกระทำที่เรียบง่ายของการเปิดซ็อกเก็ตที่มีผลผูกพันกับพอร์ตและโทร นี่เป็นส่วนหนึ่งของบริการที่ใช้สื่อสารจริงที่มีความเสี่ยงสูง ชิ้นส่วนที่เปิดbind()
และlisten()
และถึงแม้จะเป็นส่วนที่accepts()
ไม่ได้มีความเสี่ยงสูงและสามารถทำงานภายใต้การควบคุมของ superuser ได้ พวกเขาไม่ได้ใช้และดำเนินการ (ยกเว้นที่อยู่ IP ต้นทางในaccept()
กรณี) ข้อมูลที่อยู่ภายใต้การควบคุมของคนแปลกหน้าที่ไม่น่าเชื่อถือผ่านเครือข่าย
มีหลายวิธีในการทำเช่นนี้
inetd
ดังที่ Dale Hagglund กล่าวว่า "ซูเปอร์เซิร์ฟเวอร์เครือข่าย" รุ่นเก่าinetd
ทำสิ่งนี้ inetd.conf
บัญชีที่ขั้นตอนการบริการมีการเรียกใช้เป็นหนึ่งในคอลัมน์ใน มันไม่ได้แยกส่วนการฟังและสิทธิการดร็อปส่วนหนึ่งออกเป็นสองโปรแกรมเล็ก ๆ และตรวจสอบได้ง่าย แต่มันจะแยกรหัสบริการหลักออกเป็นโปรแกรมแยกต่างหากexec()
ed ในกระบวนการบริการที่วางไข่ด้วยตัวอธิบายไฟล์ที่เปิด สำหรับซ็อกเก็ต
ความยากในการตรวจสอบไม่ใช่ปัญหามากนักเนื่องจากมีเพียงการตรวจสอบโปรแกรมเดียวเท่านั้น inetd
ปัญหาที่สำคัญของการตรวจสอบไม่มาก แต่ค่อนข้างจะไม่ให้การควบคุมบริการรันไทม์แบบละเอียดอย่างง่ายเปรียบเทียบกับเครื่องมือล่าสุด
UCSPI-TCP และ daemontools
แพคเกจUCSPI-TCPและdaemontoolsของ Daniel J. Bernstein ได้รับการออกแบบให้ทำงานร่วมกัน หนึ่งสามารถใช้ชุดเครื่องมือdaemontools-encore ที่เทียบเท่ากับ Bruce Guenter ได้
โปรแกรมที่จะเปิดตัวอธิบายไฟล์ซ็อกเก็ตและเชื่อมโยงกับพอร์ตในเครื่องที่มีสิทธิใช้งานคือtcpserver
จาก UCSPI-TCP มันไม่ทั้งในและlisten()
accept()
tcpserver
แล้ว spawns ทั้งโปรแกรมบริการที่ลดลงสิทธิ์ root ตัวเอง (เพราะโปรโตคอลที่ทำหน้าที่เกี่ยวข้องกับการเริ่มต้นจากการเป็น superuser แล้ว "เข้าสู่ระบบ" เช่นเดียวกับกรณีที่มีการยกตัวอย่างเช่นการ FTP หรือภูต SSH) หรือsetuidgid
ซึ่งเป็น โปรแกรมที่มีขนาดเล็กและตรวจสอบได้ง่ายในตัวเองซึ่งจะลดสิทธิ์ แต่เพียงผู้เดียวแล้วโหลดเครือข่ายไปยังโปรแกรมบริการที่เหมาะสม (ไม่มีส่วนใดของโปรแกรมนี้ทำงานด้วยสิทธิ์ superuser อย่างที่เป็นอยู่ในกรณีนี้ด้วยqmail-smtpd
)
run
สคริปต์บริการจะเป็นตัวอย่าง (สคริปต์นี้สำหรับdummyidentdสำหรับการให้บริการ IDENT ที่ว่าง):
#!/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
อีกครั้งยูทิลิตี้วางไข่เดี่ยวและโหลดเชนอีกอัน หนึ่งมุมแหลมที่น่าสนใจของการออกแบบเป็นที่หนึ่งสามารถวางสิทธิ์ superuser หลังจากที่แต่ก่อนที่จะได้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 \
'
โปรแกรมที่ทำงานภายใต้การอุปถัมภ์ของ superuser ที่มีการบริการที่ไม่เชื่อเรื่องพระเจ้าเครื่องมือห่วงโซ่โหลดขนาดเล็กfdmove
, clearenv
, envdir
, softlimit
, และtcp-socket-listen
setuidgid
เมื่อถึงจุดsh
เริ่มต้นซ็อกเก็ตจะเปิดและเชื่อมโยงกับsmtp
พอร์ตและกระบวนการจะไม่มีสิทธิ์ superuser อีกต่อไป
s6, เครือข่าย s6 และดำเนินการ
แพ็คเกจเครือข่ายs6และเครือข่ายs6ของ Laurent Bercot ได้รับการออกแบบให้ทำงานร่วมกัน คำสั่งมีโครงสร้างคล้ายกันมากกับคำสั่งdaemontools
และ UCSPI-TCP
run
สคริปต์จะมากเหมือนกันยกเว้นสำหรับการทดแทนของs6-tcpserver
สำหรับtcpserver
และสำหรับs6-setuidgid
setuidgid
อย่างไรก็ตามหนึ่งอาจเลือกที่จะใช้ประโยชน์จากชุดเครื่องมือexeclineของ M. Bercot ในเวลาเดียวกัน
นี่คือตัวอย่างของบริการ FTP, แก้ไขเบา ๆ จากต้นฉบับของ Wayne Marshallที่ใช้ 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ของ Gerrit Pape เป็นชุดเครื่องมืออีกชุดที่ทำงานในบรรทัดเดียวกันกับ ucspi-tcp และ s6-networking เครื่องมือเป็นchpst
และtcpsvd
ในเวลานี้ แต่พวกเขาทำสิ่งเดียวกันและรหัสความเสี่ยงสูงที่ทำการอ่านประมวลผลและเขียนสิ่งต่าง ๆ ที่ส่งผ่านเครือข่ายโดยลูกค้าที่ไม่น่าไว้วางใจยังคงอยู่ในโปรแกรมแยกต่างหาก
นี่คือตัวอย่างการทำงานของM. Papefnord
ใน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 ในฐานะผู้ใช้ขั้นสูงและกระบวนการบริการที่มัน วางไข่ทำงานโดยไม่มีสิทธิ์ superuser