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


Je l'ai cherché sur Google pendant un bon bout de temps, mais je ne l'ai pas trouvé.

Je suis sous Ubuntu Linux et souhaite utiliser un serveur sur le port 80, mais en raison du mécanisme de sécurité d'Ubuntu, l'erreur suivante apparaît:

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

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


281
2017-11-10 14:31


origine


Quel est le problème pour exécuter le serveur sur un autre port non privilégié? Vous envisagez quelque chose d'aussi sévère que de désactiver le 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 connecter au port 80? Si oui, jetez-le. - Anonymous
Ou un message d'erreur Python: socket.error: [Errno 13] Permission denied - Kazark
doublon possible de Utilisateur régulier utilisant des ports inférieurs à 1024 - Roman
Tu ne peux pas. Les ports inférieurs à 1024 sont privilégiés et seul root peut ouvrir des sockets d’écoute sur ceux-ci. La bonne chose à faire est de supprimer les autorisations après l’avoir ouvert. - Falcon Momot
"Anonymous" - les utilisateurs du monde entier ont été formés à la recherche de certains services dans certains ports. Dans certains cas, il a été normalisé. Par exemple, HTTP sur le port 80 et HTTPS sur le port 443. Il est difficile de changer les utilisateurs et les normes du monde. - jww


Réponses:


Réponse courte: vous ne pouvez pas. Les ports inférieurs à 1024 ne peuvent être ouverts que par root. Selon le commentaire - vous pouvez, en utilisant 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, si ce n’est 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 en boucle (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 haut que vous décidez d'utiliser), interceptant ainsi le trafic. (Crédits à CesarB).

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

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

Cela produira 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 nr. 2, donc pour le supprimer:

# iptables -t nat -D PREROUTING 2

330
2017-11-10 14:41



@Sunny: les votes positifs ne sont pas pour le canon le plus rapide de l'ouest, mais pour les meilleures réponses. Le vôtre est le meilleur jusqu'à présent (je n'ai mentionné que iptables; vous avez en fait fourni la ligne de commande complète). La seule chose à laquelle je ne tiens pas, c’est la mise en garde concernant le fait que d’autres utilisateurs puissent également se connecter au port 8080. - CesarB
Notez que cela ne fonctionne pas avec IPv6. - Emmanuel Bourg
Quelqu'un pourrait-il expliquer comment je peux supprimer cette règle plus tard, quand je le souhaite? Après l'avoir exécuté, cela fonctionne, mais ce n'est apparemment pas une "règle" car il ne s'affiche pas quand je le fais sudo iptables --list. Je sais ce qu’est et ce que fait iptables, mais je ne l’avais jamais vraiment utilisé auparavant. - Encoderer
Merci pour votre réponse ... chaque fois que je redémarre Ubuntu, cette règle disparaît et je dois l'exécuter à nouveau. Y a-t-il un moyen de le sauver pour toujours? - Coderji
@Coderji: consultez la section "Enregistrer" de la documentation de la communauté: help.ubuntu.com/community/IptablesHowTo - Sunny


Utilisation authbind.

Cela fonctionne même avec Java si vous activez la pile Java uniquement pour IPv4. J'utilise:

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

77
2017-11-14 13:12



Si le serveur est Tomcat, vous pouvez utiliser automatiquement authbind en définissant AUTHBIND=yes dans / etc / default / tomcat6 - Emmanuel Bourg
Je ne pouvais pas obtenir que cela fonctionne sur le serveur Ubuntu avec le package Java par défaut ... - Ashley Steel
Moi non plus, aucune solution connue? - mark
Notez que vous devez configurer authbind permettre réellement que cela se produise. De la page de manuel: "/ etc / authbind / byport / port est testé. Si ce fichier est accessible pour exécution à l'utilisateur appelant, conformément à access (2), la liaison au port est autorisée.", par exemple. pour le port 80, sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80. L'installation initiale de authbind ne dispose généralement pas d'autorisations préconfigurées. - Jason C
Oh nonononononono, ne jamais rien chmod 777! - Johannes


Si votre système le prend en charge, vous pourrez peut-être utiliser des fonctionnalités. Voir les capacités man, celle dont vous avez besoin serait CAP_NET_BIND_SERVICE.

Sur les nouvelles Debian / Ubuntu, vous pouvez exécuter:

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

45
2018-05-30 20:32



cela fonctionne pour nodejs: setcap 'cap_net_bind_service = + ep' / usr / bin / nodejs - JasonS
Ce. Je me demande pourquoi cette réponse n'a pas eu plus de votes positifs. Beaucoup plus facile que l'option iptables imho. - Dominik R
C’est la réponse la plus correcte et la plus efficace. Toutes les autres réponses ont un impact négatif sur les performances ou sont simplement incertaines / peu sûres. - OneOfOne


Une autre solution consiste à configurer votre application de manière à ce qu'elle puisse se connecter au port 80. En tant que root, procédez comme suit:

chown root ./myapp
chmod +S ./myapp

Gardez à l'esprit que cela, à moins que cela ne soit absolument correct, vous exposera à des failles de sécurité potentielles, car votre application communiquera avec le réseau et fonctionnera avec tous les privilèges root. Si vous prenez cette solution, vous devriez consulter le code source d’Apache ou de Lighttpd ou quelque chose de similaire, où ils utilisent les privilèges root pour ouvrir le port, puis abandonnent immédiatement ces privilèges et "deviennent" des utilisateurs avec des privilèges inférieurs. un pirate de l'air ne peut pas s'emparer de tout votre ordinateur.

Mise à jour: comme on le voit dans cette question, il semble que les noyaux Linux depuis la version 2.6.24 disposent d’une nouvelle fonctionnalité qui vous permet de marquer un exécutable (mais pas un script, bien entendu) comme ayant le "CAP_NET_BIND_SERVICE"capacité. Si vous installez le paquet debian" libcap2-bin ", vous pouvez le faire en lançant la commande

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

39
2017-11-10 14:44



Cela revient à s’exécuter en tant que root, à moins que l’application ne sache supprimer les privilèges. - CesarB
C'est dangereux. Cela signifie que toute demande sera exécutée en tant que root. C'est pour une raison que même apache commence par se connecter en tant que root, puis transfère les privilèges à un autre utilisateur. - Sunny
Paul: iptables n’est pas si dangereux, car même si l’application est compromise, elle n’exposera pas le système en cas d’attaque, du moins avec les privilèges root. Exécuter l'application en tant que root est une autre histoire. - Sunny
Le danger pour iptables est que s’il s’agit d’un système multi-utilisateurs, comme le dit CesarB, tout le monde pouvant se lier à 8080 et intercepter le trafic. - Sunny
lol, j'adore la réponse acceptée a -15 - Evan Teran


Approche proposée par Sunny et CesarB:

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

fonctionne bien mais présente un petit inconvénient: cela n’empêche pas l’utilisateur de se connecter directement au port 8080 au lieu de 80.

Considérez le scénario suivant lorsque cela peut être 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. Si nous ne réécrivions pas soigneusement la réponse, elle serait redirigée vers https://host:8181/. À ce stade, nous sommes foutus:

  • Certains utilisateurs marqueraient le https://host:8181/ URL et nous aurions besoin de maintenir cette URL pour éviter de casser leurs signets.
  • Les 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 à 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 et 8181.


35
2018-02-20 16:19



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 des iptables pour ça. - Amala
Ça marche, vraiment cool. - xtian


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

  • apt-get install nginx

.. ou ..

  • pkg_add -r nginx 

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

Tout ce dont vous avez besoin dans nginx.conf, si vous utilisez localhost, est:

serveur {
        écoutez 80;
        nom_serveur some.domain.org;
        emplacement / {
            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;
        }
}

34
2017-11-20 14:30



J'aime beaucoup cette solution. - thomasfedb
Voici l'une des solutions suggérées par JFrog: jfrog.com/confluence/display/RTF/nginx - stolsvik


Traditionnellement sous Unix, seul root peut se lier aux ports bas (<1024).

Le moyen le plus simple de contourner ce problème consiste à exécuter votre serveur sur un ordinateur. haute port (par exemple, 8080) et utilisez une simple règle iptables pour transférer les connexions du port 80 au port 8080. Notez que cela vous fait perdre la protection supplémentaire offerte par les ports bas; n'importe quel utilisateur de votre ordinateur peut se connecter au port 8080.


29
2017-11-10 14:36





Si votre système le prend en charge, vous pourrez peut-être utiliser des fonctionnalités. Voir man capabilities, celui dont vous avez besoin serait CAP_NET_BIND_SERVICE. Non, je ne les ai jamais utilisées moi-même et je ne sais pas si elles fonctionnent vraiment :-)


23
2017-11-10 16:27



ils fonctionnent, j’utilise CAP_NET_RAW pour exécuter des outils tels que tcpdump en tant qu’utilisateur normal. - Justin