Dale Hagglund a raison. Alors je vais juste dire la même chose mais d'une manière différente, avec des détails et des exemples. ☺
La bonne chose à faire dans les mondes Unix et Linux est :
- d'avoir un petit programme, simple, facilement vérifiable, qui s'exécute en tant que super-utilisateur et lie le socket d'écoute ;
- d'avoir un autre petit programme, simple, facilement vérifiable, qui supprime les privilèges, engendré par le premier programme ;
- pour avoir la viande du service, dans un endroit séparé. troisième exécuté sous un compte non superutilisateur et chargé en chaîne par le second programme, s'attendant à hériter simplement d'un descripteur de fichier ouvert pour la socket.
Vous avez une mauvaise idée de l'endroit où se trouve le haut risque. Le risque élevé est dans lecture du réseau et action sur ce qui est lu pas dans les actes simples d'ouverture d'un socket, de liaison à un port, et d'appel listen()
. C'est la partie d'un service qui fait la communication réelle qui est à haut risque. Les parties qui s'ouvrent, bind()
y listen()
et même (dans une certaine mesure) la partie qui accepts()
ne présentent pas de risque élevé et peuvent être exécutés sous l'égide du superutilisateur. Ils n'utilisent pas et n'agissent pas sur (à l'exception des adresses IP sources dans le cadre de la accept()
cas) des données qui sont sous le contrôle d'étrangers non fiables sur le réseau.
Il existe de nombreuses façons de procéder.
inetd
Comme le dit Dale Hagglund, le vieux "superserveur de réseau" inetd
fait ceci. Le compte sous lequel le processus de service est exécuté est l'une des colonnes du tableau suivant inetd.conf
. Il ne sépare pas la partie écoute et la partie abandon de privilèges en deux programmes distincts, petits et facilement auditables, mais il sépare le code de service principal en un programme distinct, exec()
ed dans un processus de service qu'il génère avec un descripteur de fichier ouvert pour la socket.
La difficulté de l'audit n'est pas si importante, car il suffit d'auditer un seul programme. inetd
Le principal problème de l'entreprise n'est pas tant l'audit que le fait qu'elle ne fournisse pas un contrôle simple et fin des services d'exécution, par rapport à des outils plus récents.
UCSPI-TCP et daemontools
Daniel J. Bernstein UCSPI-TCP y daemontools ont été conçus pour faire cela conjointement. On peut également utiliser la méthode largement équivalente de Bruce Guenter daemontools-encore d'outils.
Le programme permettant d'ouvrir le descripteur de fichier de la socket et de se lier au port local privilégié est le suivant tcpserver
de l'UCSPI-TCP. Il fait à la fois le listen()
und die accept()
.
tcpserver
génère alors un programme de service qui perd lui-même les privilèges de l'utilisateur root (parce que le protocole servi implique de commencer en tant que superutilisateur puis de se connecter, comme c'est le cas, par exemple, avec un démon FTP ou SSH) ou setuidgid
qui est un petit programme autonome et facilement vérifiable qui abandonne uniquement les privilèges et charge ensuite en chaîne le programme de service proprement dit (dont aucune partie ne s'exécute donc jamais avec les privilèges du superutilisateur, comme c'est le cas avec, disons, qmail-smtpd
).
Un service run
script serait donc par exemple (celui-ci pour tétined pour la fourniture du service IDENT nul) :
#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl
sniffer
Mon paquet de snacks est conçu à cet effet. Il dispose d'un petit setuidgid
utilitaire, tout comme les autres. Une petite différence est qu'il est utilisable avec systemd
-LISTEN_FDS " ainsi qu'avec les services UCSPI-TCP. tcpserver
est remplacé par deux programmes distincts : tcp-socket-listen
y tcp-socket-accept
.
Là encore, les utilitaires à usage unique se multiplient et s'enchaînent les uns aux autres. Une bizarrerie intéressante de la conception est que l'on peut abandonner les privilèges de super-utilisateur après que listen()
mais avant même accept()
. Voici un run
scriptpour qmail-smtpd
qui fait exactement cela :
#!/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 \
'
Les programmes qui s'exécutent sous l'égide du super-utilisateur sont les petits outils de chargement de chaîne agnostique de services. fdmove
, clearenv
, envdir
, softlimit
, tcp-socket-listen
y setuidgid
. Au point que sh
est lancé, le socket est ouvert et lié à l'interface de l'utilisateur. smtp
et le processus n'a plus les privilèges du super-utilisateur.
s6, s6-networking, et execline
Laurent Bercot s6 y s6-réseaux ont été conçus conjointement pour cela. Les commandes sont structurellement très similaires à celles de daemontools
et UCSPI-TCP.
run
scripts seraient à peu près les mêmes, sauf pour la substitution de s6-tcpserver
para tcpserver
y s6-setuidgid
para setuidgid
. Cependant, on peut également choisir d'utiliser la méthode de M. Bercot. execline d'outils en même temps.
Voici un exemple de service FTP, légèrement modifié à partir de L'original de Wayne Marshall qui utilise execline, s6, s6-networking, et le programme de serveur FTP de fichier public :
#!/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
Gerrit Pape ipsvd est un autre jeu d'outils qui fonctionne sur le même modèle que ucspi-tcp et s6-networking. Les outils sont chpst
y tcpsvd
cette fois, mais ils font la même chose, et le code à haut risque qui fait la lecture, le traitement et l'écriture des choses envoyées sur le réseau par des clients non fiables est toujours dans un programme séparé.
Voici M. L'exemple de Pape de la course fnord
dans un run
script :
#!/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
le nouveau système de supervision des services et le système init que l'on trouve dans certaines distributions Linux, est destiné à faire ce que inetd
peut faire . Cependant, il n'utilise pas une suite de petits programmes autonomes. On doit vérifier systemd
dans son intégralité, malheureusement.
Avec systemd
on crée des fichiers de configuration pour définir un socket qui systemd
écoute, et un service qui systemd
démarre. Le fichier "unit" du service contient des paramètres qui permettent de contrôler en grande partie le processus du service, y compris l'utilisateur sous lequel il est exécuté.
Avec cet utilisateur configuré pour être un non-superutilisateur, systemd
fait tout le travail d'ouverture de la socket, la lie à un port, et appelle listen()
(et, si nécessaire, accept()
) dans le processus #1 en tant que superutilisateur, et le processus de service qu'il génère s'exécute sans les privilèges du superutilisateur.
20 votes
La réponse longue est oui... donc la réponse courte devrait aussi être oui.
6 votes
La réponse courte est oui.
1 votes
Utilisez la réponse de
noob
qui utiliseiptables
pour rediriger le trafic du port. La solution la plus simple de loin, et facile à annuler si nécessaire.0 votes
Une autre possibilité : Comment utiliser
capsh
? Notez que vous avez besoin deCAP_NET_BIND_SERVICE
.