L'application Node.js ne peut pas s'exécuter sur le port 80 même s'il n'y a pas d'autre processus bloquant le port

94

J'exécute une instance de Debian sur Amazon EC2 avec Node.js installé. Si j'exécute le code ci-dessous:

http = require('http');

http.createServer(function (request, response){
  response.writeHead(200, {'Content-Type':'text/plain'});
  response.end('Hello World\n');
}).listen(80);
console.log("Running server at port 80");

J'obtiens la sortie ci-dessous qui m'indique qu'un autre processus écoute sur le port 80:

Running server at port 80

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: listen EACCES
    at errnoException (net.js:901:11)
    at Server._listen2 (net.js:1020:19)
    at listen (net.js:1061:10)
    at Server.listen (net.js:1127:5)
    at Object.<anonymous> (/home/admin/nodetests/nodetest.js:6:4)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

Maintenant, quand je vérifie si un processus (en tant que root au cas où quelque chose serait caché) écoute sur le port 80 en utilisant:

netstat -tupln

J'obtiens la sortie ci-dessous, qui me dit qu'il n'y a rien d'écoute sur le port 80:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1667/sshd       
tcp6       0      0 :::22                   :::*                    LISTEN      1667/sshd

Je dois noter que le debian a le port 80 ouvert comme règle entrante si cela fait une différence.

Ma question est: qu'est-ce que je fais mal? Comment se fait-il que je ne puisse pas identifier le processus écoutant le port 80? Pourquoi est-il bloqué dans Debian? Quelles étapes dois-je suivre pour que le code s'exécute correctement?

Brian Yeh
la source

Réponses:

197

Le code d'erreur EACCESsignifie que vous ne disposez pas des autorisations appropriées pour exécuter des applications sur ce port. Sur les systèmes Linux, tout port inférieur à 1024 nécessite un accès root.

hexacyanide
la source
5
ainsi, sudo node myapp.js le fera si vous avez l'autorisation d'utiliser sudo (il suffit de le clouer pour tous les débutants).
AlexMA
20
@AlexMA mais exécuter un serveur en tant que root est un gros non non
Patrick Evans
1
Alors, comment exécutez-vous le nœud sur le port 80? Devriez-vous simplement ... ne pas utiliser un proxy?
AlexMA
9
@PatrickEvans Je suppose que la meilleure pratique serait de fonctionner sur un port différent et de simplement configurer une règle de redirection de port comme mentionné ici: stackoverflow.com/questions/16573668/…
AlexMA
73

Au lieu de fonctionner sur le port 80, vous pouvez rediriger le port 80 vers le port de votre application (> 1024) en utilisant

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

Cela fonctionnera si votre application s'exécute sur le port 3000.

Kamrul
la source
1
fait cela. J'ai découvert que vous devez être root pour exécuter iptables dans une nouvelle installation Deian, sinon $ PATH ne le pointera pas.
Brian Yeh
Oui, c'était probablement le moyen le plus simple de le faire. Je suis sur Google Cloud Compute, ce qui m'a posé des problèmes en touchant le port 80. C'était génial. Merci.
Andy
Cela devrait être la solution acceptée. L'exécution du serveur Web en tant que sudo est dangereuse, donnant potentiellement à un attaquant un accès root en cas de vulnérabilité dans l'application; De plus, si l'application créait des fichiers, ils seraient inaccessibles aux autres utilisateurs, ce qui vous obligerait à en utiliser sudoencore plus.
jesusiniesta
Je ne sais pas pourquoi, mais sur Ubuntu 14.04, cela n'a pas fonctionné pour moi. J'utilise maintenant la redirection de port via ssh, ce qui est tout aussi simple. J'ai posté une réponse ci-dessous .
panepeter
19

Réponse courte: Vous pouvez autoriser l'accès du nœud à ce port en utilisant:

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

longue réponse

Éditer:

Peut ne pas fonctionner sur les nouvelles versions de nœud

Reut Sharabani
la source
cela a fait l'affaire. @LinuxMint - sudo setcap 'cap_net_bind_service = + ep' / usr / local / bin / node
Combinez le
Parfois, une mise à jour modifiera le chemin de l'emplacement vers le nœud, et cela cessera de fonctionner. Vous devrez donc l'exécuter à nouveau pour le nouveau chemin d'accès au nœud.
moteur à vapeur du
Il semble que cela ne fonctionnera plus après la version 8 du nœud. Github.com/nodejs/node/issues/22648
timaw
6

Notez que si vous avez en apachecours d' exécution, vous pouvez créer un proxy inverse sur un vhost. Si votre nœud fonctionne sur le port 8080:

<VirtualHost 127.0.0.1:80>
        ServerName myLocalServer

        ProxyPass        /  http://localhost:8080/
        ProxyPassReverse /  http://localhost:8080/
</VirtualHost>

Bien sûr, ajoutez un serveur à /etc/hosts:

127.0.0.1    myLocalServer

Vous devrez activer les modules apache appropriés:

sudo a2enmod proxy_html
sudo a2enmod proxy_http
sudo a2enmod proxy_connect
sudo a2enmod proxy_ajp
sudo service apache2 restart

... et maintenant vous pouvez vous connecter http://myLocalServer.

Redsandro
la source
3

Pour ceux qui recherchent une solution simple et rapide pour un environnement de développement , la redirection de port via ssh peut être une bonne alternative:

ssh -L 80:localhost:3000 yourusername@localhost -N

Cela transfère le port 80 sur localhost au port 3000 sur localhost.

Il doit être exécuté en tant que root (port privilégié). Pour l'annuler, appuyez simplement sur ctrl-c dans le terminal. (Vous pouvez ajouter l' -findicateur pour que la commande s'exécute en arrière-plan, mais vous devez ensuite le retrouver pour le tuer).

Cette solution nécessite que vous disposiez d' un serveur ssh fonctionnant localement . Cela peut être fait rapidement , mais veuillez garder à l'esprit les implications de sécurité si vous êtes sur un réseau partagé. Vous voudrez peut-être appliquer au moins un certain niveau de sécurité supplémentaire (désactiver le mot de passe et la connexion root).

Personnellement, je ne l'utilise que sur ma machine locale. Je ne sais pas comment cela affecte la vitesse de traitement de vos demandes si vous l'exécutez en production, peut-être que quelqu'un a une idée. Quoi qu'il en soit, vous devez vous assurer que cette commande continue de s'exécuter tout le temps, ce qui introduit plus de maux de tête. Pour les environnements de production , je suggère d'utiliser un proxy inverse comme nginx .

panepeter
la source
2

la réponse hexacyanide est juste. mais y a-t-il une solution pour que cela fonctionne?

la réponse est oui.

Comment?

vous pouvez utiliser un reverse proxypar exemple, exécuter un nginx reverse proxyport sur 80et transmettre le proxy à la destination ip:portque le nœud l'utilise.

vous pouvez configurer cela en utilisant ce docker containerqui rend la vie encore plus facile. c'est la version officielle de nginx dans docker hub que vous pouvez tirer.

il y a encore plus d'avantages à utiliser reverse proxyque vous pouvez le rechercher sur Google.

Ali_Hr
la source
0

J'ai eu la même erreur et j'ai essayé d'exécuter mon application en utilisant sudo et cela a fonctionné pour moi.

sans sudo

mansi@mansi:~/NodePractice$ node myFirst.js 
events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: listen EACCES 0.0.0.0:80
    at Object.exports._errnoException (util.js:870:11)
    at exports._exceptionWithHostPort (util.js:893:20)
    at Server._listen2 (net.js:1224:19)
    at listen (net.js:1273:10)
    at Server.listen (net.js:1369:5)
    at Object.<anonymous> (/home/mansi/NodePractice/myFirst.js:6:4)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)

et avec sudo

mansi@mansi:~/NodePractice$ sudo node myFirst.js 
^C
Parth Pachchigar
la source
... c'est exactement ce que vous ne voulez pas faire. Cela crée des problèmes de sécurité.
bvdb
-1

L'utilisation de PORT 80 nécessite des autorisations spéciales. L'utilisation sudoavant l'exécution de la déclaration de l'application a résolu mon problème. par exemple, si vous utilisez npm pour exécuter votre application, vous pouvez tapersudo npm start

webcrawler
la source
1
Cette réponse n'ajoute rien pour répondre au contenu déjà fourni par d'autres. Veuillez ne répondre que si vous ajoutez des informations supplémentaires.
Brian Yeh
-2

Le code d'erreur EACCESsignifie que vous ne disposez pas des autorisations appropriées pour exécuter des applications sur ce port. Sur les systèmes Linux, tout port inférieur à 1024 nécessite un accès root.

Exécutez le programme avec sudo autorisation. Exécutez la sudo sucommande avant d'exécuter le programme.

akshith ranjan
la source
Voir les commentaires sous la réponse hexacyanides. Merci.
Brian Yeh