La aplicación Node.js no se puede ejecutar en el puerto 80 aunque no haya ningún otro proceso que bloquee el puerto


94

Estoy ejecutando una instancia de Debian en Amazon EC2 con Node.js instalado. Si ejecuto el siguiente código:

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");

Obtengo la salida a continuación que me dice que hay otro proceso escuchando en el puerto 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)

Ahora, cuando verifico si hay un proceso (como root en caso de que algo esté oculto) escuchando en el puerto 80 usando:

netstat -tupln

Obtengo la siguiente salida, que me dice que no hay nada escuchando en el puerto 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

Debo señalar que Debian tiene el puerto 80 abierto como una regla de entrada si eso hace una diferencia.

Mi pregunta es: ¿Qué estoy haciendo mal? ¿Por qué no puedo identificar el proceso que escucha el puerto 80? ¿Por qué está bloqueado en Debian? ¿Qué pasos debo seguir para que el código se ejecute correctamente?

Respuestas:


197

El código de error EACCESsignifica que no tiene los permisos adecuados para ejecutar aplicaciones en ese puerto. En los sistemas Linux, cualquier puerto por debajo de 1024 requiere acceso de root.


5
por lo tanto, el nodo sudo myapp.js lo hará si tiene autorización para usar sudo (simplemente ajústelo para cualquier principiante).
AlexMA

20
@AlexMA, pero ejecutar un servidor como root es un gran no, no
Patrick Evans

1
Entonces, ¿cómo se ejecuta el nodo en el puerto 80? ¿Deberías simplemente ... no y usar un proxy?
AlexMA

9
@PatrickEvans Supongo que la mejor práctica sería ejecutar en un puerto diferente y simplemente configurar una regla de reenvío de puertos como se menciona aquí: stackoverflow.com/questions/16573668/…
AlexMA

73

En lugar de ejecutar en el puerto 80, puede redirigir el puerto 80 al puerto de su aplicación (> 1024) usando

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

Esto funcionará si su aplicación se ejecuta en el puerto 3000.


1
hice esto. Descubrí que tienes que ser root para ejecutar iptables en una instalación nueva de Debian, de lo contrario $ PATH no lo señalará.
Brian Yeh

Sí, esta fue probablemente la forma más fácil de hacerlo. Estoy en Google Cloud Compute, lo que me dio problemas al tocar el puerto 80. Fue genial. Gracias.
Andy

Esta debería ser la solución aceptada. Ejecutar el servidor web como sudo es peligroso, ya que puede dar acceso de root al atacante si existe alguna vulnerabilidad en la aplicación; Además, si la aplicación creara archivos, serían inaccesibles para otros usuarios, lo que haría que los usara sudoaún más.
jesusiniesta

No estoy seguro de por qué, pero en Ubuntu 14.04 esto no funcionó para mí. Ahora uso el reenvío de puertos a través de ssh, que es igual de fácil. Publiqué una respuesta a continuación .
panelista

19

Respuesta corta: puede permitir el acceso del nodo a ese puerto usando:

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

respuesta larga

Editar:

Puede que no funcione en nuevas versiones de nodos


eso hizo el truco. @LinuxMint - sudo setcap 'cap_net_bind_service = + ep' / usr / local / bin / node
Combine

A veces, una actualización cambiará la ruta de ubicación al nodo y esto dejará de funcionar. Por lo tanto, deberá ejecutarlo nuevamente para la nueva ruta al nodo.
vaporizado el

Parece que esto ya no funcionará después de la versión 8 del nodo. Github.com/nodejs/node/issues/22648
timaw

6

Tenga en cuenta que si lo está apacheejecutando, puede crear un proxy inverso en un vhost. Si su nodo se está ejecutando en el puerto 8080:

<VirtualHost 127.0.0.1:80>
        ServerName myLocalServer

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

Por supuesto, agregue el servidor a /etc/hosts:

127.0.0.1    myLocalServer

Deberá habilitar los módulos de apache relevantes:

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

... y ahora puedes conectarte a http://myLocalServer.


3

Para aquellos que buscan una solución rápida y sencilla para un entorno de desarrollo , el reenvío de puertos a través de ssh puede ser una buena alternativa:

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

Esto reenvía el puerto 80 en localhost al puerto 3000 en localhost.

Debe ejecutarse como root (puerto privilegiado). Para cancelarlo, simplemente presione ctrl-c en la terminal. (Puede agregar el-f bandera para que el comando se ejecute en segundo plano, pero luego debe encontrarlo nuevamente para eliminarlo).

Esta solución requiere que tenga un servidor ssh que se ejecute localmente . Se puede hacer rápidamente , pero tenga en cuenta las implicaciones de seguridad si está en una red compartida. Es posible que desee aplicar al menos algún nivel de seguridad adicional (deshabilite la contraseña y el inicio de sesión de root).

Personalmente, solo uso esto en mi máquina local. No estoy seguro de cómo afecta la velocidad de procesamiento de sus solicitudes si ejecuta esto en producción, tal vez alguien tenga una idea. De todos modos, debe asegurarse de que este comando se siga ejecutando todo el tiempo, lo que presenta más dolores de cabeza. Para entornos de producción , sugiero usar un proxy inverso como nginx .


2

la respuesta del hexacianuro es correcta. pero ¿hay alguna solución para que esto funcione?

la respuesta es sí.

¿cómo?

puede usar, reverse proxypor ejemplo, ejecutar un nginx reverse proxypuerto 80y pasar el proxy al destinoip:port que el nodo lo usa.

puede configurar esto usando docker containerque hace la vida aún más fácil. esta es la compilación oficial de nginx en docker hub que puede extraer.

hay incluso más beneficios en el uso reverse proxyque puede buscar en Google.


0

Recibí el mismo error e intenté ejecutar mi aplicación usando sudo y funcionó para mí.

sin 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)

y con sudo

mansi@mansi:~/NodePractice$ sudo node myFirst.js 
^C

... que es exactamente lo que no quieres hacer. Crea problemas de seguridad.
bvdb

-1

El uso de PORT 80 requiere algunos permisos especiales. Usar sudoantes de ejecutar la declaración de la aplicación resolvió mi problema. por ejemplo, si usa npm para ejecutar su aplicación, puede escribirsudo npm start


1
Esta respuesta no agrega nada al contenido de respuesta ya proporcionado por otros. Responda únicamente si está agregando información adicional.
Brian Yeh

-2

El código de error EACCESsignifica que no tiene los permisos adecuados para ejecutar aplicaciones en ese puerto. En los sistemas Linux, cualquier puerto por debajo de 1024 requiere acceso de root.

Ejecute el programa con sudopermiso. Ejecute el sudo sucomando antes de ejecutar el programa.


Vea los comentarios de la publicación en la respuesta de hexacianuros. Gracias.
Brian Yeh
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.