409 votes

Comment faire fonctionner un serveur sur le port 80 en tant qu'utilisateur normal sous Linux ?

J'ai cherché une solution sur Google pendant un certain temps, mais je n'ai pas trouvé de réponse.

Je suis sur Ubuntu Linux et je veux exécuter un serveur sur le port 80, mais en raison du mécanisme de sécurité d'Ubuntu, j'obtiens l'erreur suivante :

java.net.BindException : Permission refusée:80

Je pense qu'il devrait être assez simple de désactiver ce mécanisme de sécurité afin que le port 80 soit disponible pour tous les utilisateurs ou d'attribuer les privilèges nécessaires à l'utilisateur actuel pour accéder au port 80.

4 votes

Quel est le problème pour faire fonctionner le serveur sur un autre port qui n'est pas privilégié ? Vous envisagez une mesure aussi sévère que la désactivation du mécanisme de sécurité sans fournir au moins une raison très sérieuse d'exécuter un serveur sur ce port. Le serveur est-il codé en dur pour se lier au port 80 ? Si c'est le cas, jetez-le.

0 votes

Ou un message d'erreur Python : socket.error: [Errno 13] Permission denied

6 votes

429voto

Paul Roub Points 11185

Réponse courte : vous ne pouvez pas. Les ports inférieurs à 1024 ne peuvent être ouverts que par le root. Pour ce qui est du commentaire, vous pouvez utiliser la fonction CAP_NET_BIND_SERVICE Mais cette approche, appliquée à java bin, fera que tout programme java sera exécuté avec ce paramètre, ce qui est indésirable, voire un risque pour la sécurité.

La réponse longue : vous pouvez rediriger les connexions sur le port 80 vers un autre port que vous pouvez ouvrir en tant qu'utilisateur normal.

Exécuter en tant que root :

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Comme les périphériques de bouclage (comme localhost) n'utilisent pas les règles de préroutage, si vous devez utiliser localhost, etc., ajoutez également cette règle ( Merci @Francesco ) :

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

NOTE : La solution ci-dessus n'est pas bien adapté aux systèmes multi-utilisateurs, car tout utilisateur peut ouvrir le port 8080 (ou tout autre port élevé que vous décidez d'utiliser), interceptant ainsi le trafic. (Crédits à CesarB ).

EDIT : selon la question du commentaire - pour supprimer la règle ci-dessus :

# iptables -t nat --line-numbers -n -L

Cela donnera quelque chose comme :

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 redir ports 8088
2    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 8080

La règle qui vous intéresse est la n°2, donc à supprimer :

# iptables -t nat -D PREROUTING 2

0 votes

Je vois que d'autres ont posté plus rapidement que moi. Je vais laisser ma réponse juste pour la ligne de commande iptables, mais s'il vous plaît, votez les autres réponses, pas la mienne.

21 votes

@Sunny : les upvotes ne sont pas pour le pistolet le plus rapide de l'ouest, mais pour les meilleures réponses. La vôtre est la meilleure jusqu'à présent (je n'ai mentionné qu'iptables ; vous avez en fait fourni la ligne de commande complète). La seule chose que la mienne a et que la vôtre n'a pas, c'est l'avertissement concernant la possibilité pour les autres utilisateurs de se lier au port 8080.

0 votes

CesarB : de toute façon, vous avez votre +1.

93voto

Otto Kekäläinen Points 921

Si votre système le supporte, vous pouvez peut-être utiliser les capacités. Voir man capabilities, celui dont vous avez besoin est CAP_NET_BIND_SERVICE.

Sur les plus récentes versions de Debian/Ubuntu, vous pouvez exécuter :

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program

1 votes

Cela fonctionne pour nodejs : setcap 'cap_net_bind_service=+ep' /usr/bin/nodejs

7 votes

Ceci. Je me demande pourquoi cette réponse n'a pas plus de votes positifs. Beaucoup plus facile que l'option iptables, à mon avis.

9 votes

C'est la réponse correcte et la plus efficace, toutes les autres réponses entraînent une baisse des performances ou sont simplement douteuses ou peu sûres.

89voto

geocar Points 2287

Utilisez authbind .

Il fonctionne même avec Java si vous activez la pile IPv4 uniquement de Java. Je l'utilise :

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …

5 votes

Si le serveur est Tomcat, vous pouvez utiliser authbind automatiquement en configurant AUTHBIND=yes dans /etc/default/tomcat6

0 votes

Je n'ai pas réussi à le faire fonctionner sur le serveur Ubuntu avec le paquetage Java par défaut...

0 votes

Moi non plus, une solution connue ?

55voto

CosmicB Points 491

J'utilise simplement Nginx en amont. Il peut aussi fonctionner sur localhost.

  • apt-get install nginx

..ou

  • pkg_add -r nginx

ou ce qui convient le mieux à votre système d'exploitation.

Tout ce dont vous avez besoin dans nginx.conf, s'il fonctionne sur localhost, est :

server {
        listen  80;
        server\_name some.domain.org;
        location / {
            proxy\_set\_header    Host $host;
            proxy\_set\_header    X-Real-IP   $remote\_addr;
            proxy\_set\_header    X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
            proxy\_pass  http://127.0.0.1:8081;
        }
}

0 votes

J'aime beaucoup cette solution.

1 votes

C'est l'une des solutions proposées par JFrog : jfrog.com/confluence/display/RTF/nginx

38voto

xelurg Points 1655

Approche proposée par Sunny et CesarB :

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

fonctionne bien mais il a un petit inconvénient : il n'empêche pas l'utilisateur de se connecter directement au port 8080 au lieu de 80.

Considérez le scénario suivant dans lequel cela peut poser un problème.

Disons que nous avons un serveur qui accepte les connexions HTTP sur le port 8080 et les connexions HTTPS sur le port 8181.

Nous utilisons iptables pour établir les redirections suivantes :

80  ---> 8080
443 ---> 8181

Supposons maintenant que notre serveur décide de rediriger l'utilisateur d'une page HTTP vers une page HTTPS. A moins que nous ne réécrivions soigneusement la réponse, elle sera redirigée vers https://host:8181/ . A ce stade, nous sommes foutus :

  • Certains utilisateurs mettront un signet sur le https://host:8181/ et nous devrions maintenir cette URL pour éviter de briser leurs signets.
  • D'autres utilisateurs ne pourraient pas se connecter car leurs serveurs proxy ne prennent pas en charge les ports SSL non standard.

J'utilise l'approche suivante :

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT

Combinée avec la règle REJECT par défaut sur la chaîne INPUT, cette approche empêche les utilisateurs de se connecter directement aux ports 8080, 8181.

2 votes

C'est bien, mais pourquoi ne pas simplement lier le démon à localhost:8080 au lieu de 0.0.0.0:8080 ? Je veux faire ça, mais j'ai besoin d'iptables pour ça.

0 votes

Ça marche, c'est vraiment cool.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X