Permettre à un utilisateur de laisser écouter un port inférieur à 1024

63

Je dois autoriser un utilisateur (différent de root) à exécuter un serveur à l'écoute sur le port 80.

Est-ce qu'il y a un moyen de faire ça?

peoro
la source
1
Cette question est sujette à interprétation. J'espère que vous voulez dire "vous avez créé un nouveau service système que vous (en tant qu'utilisateur root) voudriez exécuter sur un compte non privilégié pour des raisons de sécurité" (considéré comme une bonne pratique) et non pas "j'ai un utilisateur qui lui a demandé s'il le pouvait. exécuter leur propre serveur Web sur mon système, comment puis-je leur permettre l'accès? " (considéré comme pratique plutôt médiocre)
Michael Shaw
3
@Ptolemy, la raison réelle est: ma machine est derrière un pare-feu qui bloque tous les ports sauf le 80. Je veux héberger un serveur (qui ne lâche pas de privilèges!), Il faut donc qu'il écoute sur le port 80, mais ne lui faites pas confiance pour s’exécuter en tant que root (pour des raisons évidentes de sécurité). Je suis autorisé à le faire, si vous vous en souciez.
peoro
serverfault.com/questions/112795/…
Ciro Santilli a annoncé le

Réponses:

50

setcap 'cap_net_bind_service=+ep' /path/to/program

cela fonctionnera pour des processus spécifiques. Mais pour permettre à un utilisateur particulier de se lier aux ports inférieurs à 1024, vous devrez l’ajouter aux utilisateurs sudoers.

Regardez cette discussion pour plus.

Rohan Monga
la source
31

(Certaines de ces méthodes ont été mentionnées dans d'autres réponses; je donne plusieurs choix possibles par ordre de préférence approximatif.)

Vous pouvez rediriger le port bas sur un port haut et écouter sur le port haut.

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080

Vous pouvez démarrer votre serveur en tant que root et supprimer des privilèges une fois qu'il a commencé à écouter sur le port privilégié. De préférence, plutôt que de le coder vous-même, démarrez votre serveur à partir d'un wrapper qui fait le travail à votre place. Si votre serveur démarre une instance par connexion, démarrez-le depuis inetd(ou un programme similaire tel que xinetd). Pour inetd, utilisez une ligne comme celle-ci dans /etc/inetd.conf:

http  stream  tcp  nowait  username:groupname  /path/to/server/executable  argv[0] argv[1]…

Si votre serveur écoute en une seule instance, démarrez-le à partir d'un programme tel que authbind. Soit créer un fichier vide /etc/authbind/byport/80et le rendre exécutable pour l'utilisateur qui exécute le serveur; ou create /etc/authbind/byuid/1234, où 1234 est l'UID exécutant le serveur, contenant la ligne 0.0.0.0/0:80,80.

Si votre exécutable du serveur est stocké sur un système de fichiers qui prend en charge les capacités, vous pouvez lui donner la capacité . Attention, les fonctionnalités sont encore relativement nouvelles et ont encore quelques problèmes .cap_net_bind_service

setcap cap_net_bind_service=ep /path/to/server/executable
Gilles, arrête de faire le mal
la source
4
Dans tous les cas que j'ai eu à traiter, l'exécutable était un script qui lançait java ou python. En tant que personne qui n'a pas 10 heures à consacrer aux détails, votre solution iptables le couvre sans douleur.
srking
Pour la solution iptables, je devais également ajouter une règle de filtrage, -A INPUT -p tcp --dport 1080 -j ACCEPTsans quoi cela ne fonctionnerait pas (j'ai aussi une -j DROPfourre-tout.) Il me reste donc deux sockets d'écoute.
thom_nic
4

La réponse courte est que cela n’est pas possible par conception.

La réponse longue est que dans les mondes open source, beaucoup de personnes jouent avec le design et proposent des méthodes alternatives. En général, il est largement admis que cela ne devrait pas être possible. Le fait d'essayer signifie probablement que vous avez un autre défaut de conception dans votre système et que vous devez reconsidérer l'architecture de votre système tout entier à la lumière des meilleures pratiques * nix et des implications en matière de sécurité.

Cela dit, l'un des programmes permettant d'autoriser l'accès non root aux ports bas est authbind . Les deux SELinux et grsecurity fournissent également des cadres pour les authentifications à l' écoute de fines.

Enfin, si vous voulez que des utilisateurs spécifiques exécutent des programmes spécifiques en tant que root et que vous ayez vraiment besoin de permettre à un utilisateur de redémarrer Apache ou quelque chose du genre, sudoc'est votre ami!

Caleb
la source
8
La "sécurité" des ports ne vous apporte pas vraiment grand chose dans le monde moderne.
pjc50
3
@ pjc50: Oui c'est le cas. Il s'agit de confiance implicite. Un faible nombre de ports implique une grande confiance. Les démons SSH, POP, FTP et autres sont censés demander des mots de passe de niveau système et d’autres identifiants lors de l’ouverture de leurs ports. Si les utilisateurs étaient autorisés à écouter des ports bas sur une boîte, ils pourraient démarrer des démons factices sur des ports inutilisés (ou bloqués) et collecter des mots de passe d'utilisateurs sans méfiance. Ces mots de passe pourraient ensuite être utilisés sur cette zone pour compromettre d'autres comptes, y compris le compte root.
Caleb
8
C'est une forme de sécurité assez faible. Si vous vous êtes connecté à quelque chose et que vous n'avez pas effectué de transaction de certificat, vous n'avez aucune idée de qui vous parlez, c'est-à-dire des attaques MITM.
pjc50
5
Je suppose que ce qui est nécessaire est chown pour les ports: vous pouvez alors "chown mail port25", puis (a) votre démon de messagerie n'a pas besoin d'être démarré avec des privilèges root et (b) personne d'autre ne peut le pirater.
pjc50
7
Bien que cela ait pu être vrai "à dessein" quand Linux était à ses balbutiements, cela n'a pas beaucoup de sens à l'époque et maintenant. La sécurité concerne tout ce qu'un utilisateur peut et ne peut pas faire. Par exemple, permettre à l'utilisateur root d'utiliser le port 80, par exemple, représente un risque énorme pour la sécurité, car cela signifie que vous devez donner un accès root aux personnes qui doivent utiliser le port 80 mais ne devraient pas en avoir. Si vous confiez à un utilisateur X non root l’utilisation du port 80, vous devriez pouvoir coder cette confiance dans votre système d’exploitation. Heureusement, comme vous l'avez mentionné, il existe des solutions de contournement qui permettent cela, comme authbind.
BT
3

Vous pouvez utiliser la redirection de port netcat ou xinetd ou iptables, ou utiliser apache en tant que proxy frontal et exécuter le processus sur un port non privilégié.

Jamespo
la source
3

Authbind , @Gilles en a déjà parlé, mais j'aimerais développer un peu.

Il offre un contrôle d’accès pratique (détails dans la page de manuel): vous pouvez filtrer les accès par port, adresse d’interface, uid, plages d’adresse ou de port et combinaison de ceux-ci.

Il a un paramètre très utile --depth:

- niveaux de profondeur

Force authbind à affecter les programmes situés au plus profond du graphe appelant. La valeur par défaut est 1.

"Niveaux profonds" signifie quand un script (ou un programme) exécute un autre script qui descend d'un niveau. Donc, si vous avez --depth 5cela signifie aux niveaux 1 (ou est-ce que c'est 0?) À 5, vous avez la permission de vous lier, alors qu'au niveau 6 et plus, vous n'avez pas. Utile lorsque vous voulez qu'un script ait accès, mais pas les programmes qu'il exécute avec ou sans votre connaissance.


Pour illustrer cela, vous pourriez avoir quelque chose comme ceci: pour des raisons de sécurité, vous avez un utilisateur javaqui est uniquement destiné à exécuter java et vous souhaitez lui donner accès au port 80:

echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80

J'ai créé le ../byport/80 file, le donné à un javagroupe d'utilisateurs (chaque utilisateur a son propre groupe) et je l'ai rendu exécutable par groupe, ce qui signifie qu'il est exécutable par javautilisateur. Si vous donnez l'accès par port, le fichier doit être exécutable par l'utilisateur qui devrait y avoir accès. C'est ce que nous avons fait.

Cela peut être suffisant pour le Joe moyen, mais comme vous savez utiliser le --depthparamètre, vous lancez (en tant javaqu'utilisateur) en authbind --depth [depth] my_web_app's_start_scriptcommençant --depth 1et en remontant jusqu'à ce que vous trouviez la plus petite profondeur qui fonctionne et que vous l'utilisiez.

Lisez la page de manuel pour plus de détails .

Dominykas Mostauskis
la source
1

J'ai essayé la méthode iptables PREROUTING REDIRECT, mais j'ai constaté qu'elle affecte également les paquets transférés. Autrement dit, si la machine transfère également des paquets entre des interfaces (par exemple, si elle agit comme un point d’accès Wi-Fi connecté à un réseau Ethernet), la règle iptables intercepte également les connexions des clients connectés aux destinations Internet et les redirige vers la machine. Ce n'est pas ce que je voulais, je voulais seulement rediriger les connexions qui étaient dirigées vers la machine elle-même.

Une possibilité consiste à utiliser le transfert de port TCP. Par exemple, en utilisant socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

Toutefois, l’un des inconvénients de cette méthode est que l’application qui écoute sur le port 8080 ne connaît pas l’adresse source des connexions entrantes (par exemple, à des fins de journalisation ou d’identification).

Craig McQueen
la source