GNU/Linux >> Tutoriels Linux >  >> Linux

Autoriser le processus non root à se lier aux ports 80 et 443 ?

Je ne sais pas à quoi font référence les autres réponses et commentaires ici. C'est possible assez facilement. Il existe deux options, qui permettent toutes deux d'accéder aux ports à faible numéro sans avoir à élever le processus à root :

Option 1 :Utiliser CAP_NET_BIND_SERVICE pour accorder un accès au port à faible numéro à un processus :

Avec cela, vous pouvez accorder un accès permanent à un binaire spécifique pour se lier aux ports à faible numéro via le setcap commande :

sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary

Pour plus de détails sur la partie e/i/p, voir cap_from_text .

Après avoir fait cela, /path/to/binary sera en mesure de se lier aux ports à faible numéro. Notez que vous devez utiliser setcap sur le binaire lui-même plutôt que sur un lien symbolique.

Option 2 :Utilisez authbind pour accorder un accès unique, avec un contrôle utilisateur/groupe/port plus fin :

Le authbind L'outil (page de manuel) existe précisément pour cela.

  1. Installer authbind en utilisant votre gestionnaire de paquets préféré.

  2. Configurez-le pour accorder l'accès aux ports pertinents, par ex. pour autoriser 80 et 443 de tous les utilisateurs et groupes :

    sudo touch /etc/authbind/byport/80
    sudo touch /etc/authbind/byport/443
    sudo chmod 777 /etc/authbind/byport/80
    sudo chmod 777 /etc/authbind/byport/443
    
  3. Exécutez maintenant votre commande via authbind (en spécifiant éventuellement --deep ou d'autres arguments, voir la page de manuel):

    authbind --deep /path/to/binary command line args
    

    Par exemple

    authbind --deep java -jar SomeServer.jar
    

Il y a des avantages et des inconvénients dans les deux cas ci-dessus. L'option 1 accorde la confiance au binaire mais ne fournit aucun contrôle sur l'accès par port. L'option 2 accorde la confiance à l'utilisateur/groupe et fournit un contrôle sur l'accès par port, mais les anciennes versions ne prenaient en charge que IPv4 (depuis que j'ai écrit ceci à l'origine, des versions plus récentes prenant en charge IPv6 ont été publiées).


Dale Hagglund est sur place. Donc je vais juste dire la même chose mais d'une manière différente, avec quelques détails et exemples. ☺

La bonne chose à faire dans les mondes Unix et Linux est :

  • avoir un petit programme simple, facilement vérifiable, qui s'exécute en tant que superutilisateur et lie le socket d'écoute ;
  • pour avoir un autre petit programme simple, facilement vérifiable, qui supprime les privilèges générés par le premier programme ;
  • avoir la viande du service, dans un tiers séparé programme, exécuté sous un compte non-superutilisateur et chargé en chaîne par le deuxième programme, s'attendant à hériter simplement d'un descripteur de fichier ouvert pour le socket.

Vous avez une mauvaise idée de l'endroit où se trouve le risque élevé. Le risque élevé est de lire à partir du réseau et d'agir sur ce qui est lu pas dans le simple fait d'ouvrir un socket, de le lier à un port et d'appeler listen() . C'est la partie d'un service qui fait la communication réelle qui présente un risque élevé. Les parties qui s'ouvrent, bind() , et 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 source dans le 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, l'ancien "superserveur réseau" inetd est ce que ca. Le compte sous lequel le processus de service est exécuté est l'une des colonnes de inetd.conf . Il ne sépare pas la partie écoute et la partie suppression des privilèges en deux programmes distincts, petits et facilement auditables, mais il sépare le code de service principal dans un programme séparé, exec() ed dans un processus de service qu'il génère avec un descripteur de fichier ouvert pour le socket.

La difficulté de l'audit n'est pas vraiment un problème, car il suffit d'auditer un seul programme. inetd Le problème majeur de n'est pas tant l'audit, mais plutôt le fait qu'il ne fournit pas un contrôle simple et précis du service d'exécution, par rapport aux outils plus récents.

UCSPI-TCP et daemontools

Les packages UCSPI-TCP et daemontools de Daniel J. Bernstein ont été conçus pour faire cela conjointement. On peut également utiliser l'ensemble d'outils daemontools-encore largement équivalent de Bruce Guenter.

Le programme pour ouvrir le descripteur de fichier socket et se lier au port local privilégié est tcpserver , de l'UCSPI-TCP. Il fait à la fois le listen() et le accept() .

tcpserver puis génère soit un programme de service qui supprime lui-même les privilèges root (car le protocole servi implique de commencer en tant que superutilisateur puis de "se connecter", comme c'est le cas avec, par exemple, un démon FTP ou SSH) ou setuidgid qui est un petit programme autonome et facilement vérifiable qui supprime uniquement les privilèges, puis enchaîne les charges vers le programme de service proprement dit (dont aucune partie ne s'exécute donc jamais avec des privilèges de superutilisateur, comme c'est le cas avec, par exemple, qmail-smtpd ).

Un service run script serait donc par exemple (celui-ci pour dummyidentd pour fournir un service null IDENT):

#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl

bouffe

Mon paquet nosh est conçu pour cela. Il a un petit setuidgid utilitaire, comme les autres. Une légère différence est qu'il est utilisable avec systemd -style "LISTEN_FDS" ainsi qu'avec les services UCSPI-TCP, donc le traditionnel tcpserver programme est remplacé par deux programmes distincts :tcp-socket-listen et tcp-socket-accept .

Encore une fois, les utilitaires à usage unique apparaissent et se chargent en chaîne. Une particularité intéressante de la conception est que l'on peut supprimer les privilèges de superutilisateur après listen() mais avant même accept() . Voici un run script pour qmail-smtpd qui fait en effet 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 superutilisateur sont les petits outils de chargement de chaîne indépendants des services fdmove , clearenv , envdir , softlimit , tcp-socket-listen , et setuidgid . Au point que sh est démarré, le socket est ouvert et lié au smtp port, et le processus n'a plus de privilèges de superutilisateur.

s6, mise en réseau s6 et execline

Les packages s6 et s6-networking de Laurent Bercot ont été conçus pour faire cela conjointement. Les commandes sont structurellement très similaires à celles de daemontools et UCSPI-TCP.

run les scripts seraient à peu près les mêmes, à l'exception de la substitution de s6-tcpserver pour tcpserver et s6-setuidgid pour setuidgid . Cependant, on peut également choisir d'utiliser en même temps l'ensemble d'outils execline de M. Bercot.

Voici un exemple de service FTP, légèrement modifié par rapport à l'original de Wayne Marshall, qui utilise execline, s6, s6-networking et le programme de serveur FTP de 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 de Gerrit Pape est un autre ensemble d'outils qui fonctionne dans le même sens que ucspi-tcp et s6-networking. Les outils sont chpst et tcpsvd cette fois, mais ils font la même chose, et le code à haut risque qui lit, traite et écrit les choses envoyées sur le réseau par des clients non fiables se trouve toujours dans un programme séparé.

Voici l'exemple de M. Pape d'exécution de 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 et d'initialisation des services que l'on trouve dans certaines distributions Linux, est destiné à faire ce inetd peut faire. Cependant, il n'utilise pas une suite de petits programmes autonomes. Il faut auditer 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éparts. Le fichier "unité" de service a des paramètres qui permettent un grand contrôle sur le processus de service, y compris l'utilisateur sous lequel il s'exécute.

Avec cet utilisateur défini comme non superutilisateur, systemd fait tout le travail d'ouverture du socket, de le lier à un port et d'appeler 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 privilèges de superutilisateur.


J'ai une approche assez différente. Je voulais utiliser le port 80 pour un serveur node.js. Je n'ai pas pu le faire car Node.js a été installé pour un utilisateur non sudo. J'ai essayé d'utiliser des liens symboliques, mais cela n'a pas fonctionné pour moi.

Ensuite, j'ai appris que je pouvais transférer les connexions d'un port à un autre. J'ai donc démarré le serveur sur le port 3000 et mis en place une redirection de port du port 80 vers le port 3000.

Ce lien fournit les commandes réelles qui peuvent être utilisées pour ce faire. Voici les commandes -

hôte local/bouclage

sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 3000

externe

sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000

J'ai utilisé la deuxième commande et cela a fonctionné pour moi. Je pense donc qu'il s'agit d'un terrain d'entente pour ne pas autoriser le processus utilisateur à accéder directement aux ports inférieurs, mais leur donner l'accès à l'aide de la redirection de port.


Linux
  1. Comment ouvrir les ports 80 et 443 dans FirewallD

  2. Comment autoriser SFTP et interdire SSH ?

  3. Ssh – Comment renier un processus en cours d'exécution et l'associer à un nouveau shell d'écran ?

  4. Substitution de processus et tuyau ?

  5. Comment autoriser ou bloquer le port et l'adresse IP à l'aide de Firewalld, de tables IP et d'UFW sous Linux ?

Ubuntu 22.04 ouvre le port HTTP 80 et le port HTTPS 443 avec ufw

Comment trouver l'ID de processus d'un programme et le tuer [Astuce rapide]

Comment écrire et exécuter un programme C sous Linux

UNIX / Linux :Comment crontab valide l'accès basé sur les fichiers cron.allow et cron.deny

tracer une adresse IP et un port particuliers

Bloquer l'accès réseau d'un processus ?