Дейл Хэгглунд на месте. Так что я просто собираюсь сказать то же самое, но по-другому, с некоторыми особенностями и примерами. ☺
В мире Unix и Linux правильно сделать следующее:
- иметь небольшую, простую, легко проверяемую программу, которая работает от имени суперпользователя и связывает сокет прослушивания;
- иметь другую маленькую, простую, легко проверяемую программу, которая отбрасывает привилегии, порожденные первой программой;
- чтобы основная часть службы работала в отдельной третьей программе под учетной записью не-суперпользователя и цепью, загруженной второй программой, ожидая просто наследовать дескриптор открытого файла для сокета.
Вы неправильно поняли, где находится высокий риск. Высокий риск заключается в чтении из сети и действии в отношении того, что читается, а не в простых действиях по открытию сокета, привязке его к порту и вызову listen()
. Это часть службы, которая осуществляет фактическое общение с высоким риском. Части, которые открываются, bind()
и listen()
, и даже (в некоторой степени), части accepts()
, которые не представляют высокого риска и могут эксплуатироваться под эгидой суперпользователя. Они не используют и не обрабатывают (за исключением IP-адресов источника в данном accept()
случае) данные, которые находятся под контролем ненадежных незнакомцев по сети.
Есть много способов сделать это.
inetd
Как говорит Дейл Хагглунд, старый «сетевой суперсервер» inetd
делает это. Учетная запись, под которой запускается процесс обслуживания, является одним из столбцов в inetd.conf
. Он не разделяет часть прослушивания и часть удаления привилегий на две отдельные программы, маленькие и легко проверяемые, но он разделяет основной код службы на отдельную программу, exec()
созданную в процессе службы, который порождается дескриптором открытого файла. для розетки.
Сложность аудита - не такая уж большая проблема, поскольку нужно проверять только одну программу. inetd
Главная проблема не столько в аудите, сколько в том, что он не обеспечивает простого детального управления сервисом во время выполнения по сравнению с более поздними инструментами.
UCSPI-TCP и daemontools
Daniel J. Бернштейна UCSPI-TCP и DaemonTools пакеты были разработаны , чтобы сделать это в совокупности. В качестве альтернативы можно использовать практически эквивалентный набор инструментов Брюса Гюнтера на бис .
Программа для открытия дескриптора файла сокета и привязки к привилегированному локальному порту tcpserver
, из UCSPI-TCP. Это делает listen()
и accept()
.
tcpserver
затем порождает либо служебную программу, которая сама отбрасывает привилегии root (поскольку обслуживаемый протокол включает в себя запуск от имени суперпользователя, а затем «вход в систему», как в случае, например, с FTP или демоном SSH), или setuidgid
который является Самодостаточная небольшая и легко проверяемая программа, которая только отбрасывает привилегии и затем загружает их по цепочке в собственно сервисную программу (ни одна часть которой, таким образом, никогда не работает с привилегиями суперпользователя, как, например, в случае с qmail-smtpd
).
run
Сценарий службы , таким образом, будет, например, (этот для dummyidentd для предоставления нулевой услуги IDENT):
#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl
перекус
Мой пакет Nosh предназначен для этого. У него есть небольшая setuidgid
утилита, как и у других. Небольшое отличие состоит в том, что его можно использовать со systemd
службами -style "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
, и setuidgid
. К моменту sh
запуска сокет открыт и привязан к smtp
порту, и у процесса больше нет привилегий суперпользователя.
S6, S6-сети и Execline
Пакеты Laurent Bercot для сетей s6 и s6 были разработаны для того, чтобы сделать это совместно. Команды структурно очень похожи на команды daemontools
UCSPI-TCP.
run
сценарии были бы почти такими же, за исключением замены s6-tcpserver
для tcpserver
и s6-setuidgid
для setuidgid
. Тем не менее, можно также использовать набор инструментов execline М. Bercot в то же время.
Вот пример службы FTP, слегка модифицированной по сравнению с оригиналом Уэйна Маршалла , которая использует execline, s6, s6-network и программу сервера 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-network. Инструменты есть 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
новая система контроля и инициализации сервиса, которую можно найти в некоторых дистрибутивах Linux, предназначена для того, что inetd
может делать . Тем не менее, он не использует набор небольших автономных программ. К systemd
сожалению, нужно проводить аудит полностью.
С помощью systemd
одного создает файлы конфигурации, чтобы определить сокет, который systemd
прослушивает, и сервис, который systemd
запускается. Файл «единицы измерения» службы имеет настройки, которые позволяют значительно контролировать процесс обслуживания, в том числе, от имени какого пользователя он запускается.
С этим пользователем, установленным как не суперпользователь, он systemd
выполняет всю работу по открытию сокета, привязке его к порту и вызову listen()
(и, если требуется, accept()
) в процессе # 1 в качестве суперпользователя и в сервисном процессе, который он порождения запускаются без привилегий суперпользователя.