Die Node.js-App kann nicht auf Port 80 ausgeführt werden, obwohl kein anderer Prozess den Port blockiert

94

Ich führe eine Instanz von Debian auf Amazon EC2 mit installierter Node.js aus. Wenn ich den folgenden Code ausführe:

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

Ich erhalte die folgende Ausgabe, die mir sagt, dass an Port 80 ein anderer Prozess abhört:

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)

Wenn ich jetzt überprüfe, ob es einen Prozess gibt (als Root, falls etwas versteckt ist), der Port 80 abhört, indem ich:

netstat -tupln

Ich erhalte die folgende Ausgabe, die mir sagt, dass an Port 80 nichts zu hören ist:

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

Ich sollte beachten, dass der Debian Port 80 als eingehende Regel geöffnet hat, wenn dies einen Unterschied macht.

Meine Frage ist: Was mache ich falsch? Wie kommt es, dass ich den Prozess, der Port 80 abhört, nicht identifizieren kann? Warum ist es in Debian blockiert? Welche Schritte muss ich unternehmen, damit der Code ordnungsgemäß ausgeführt wird?

Brian Yeh
quelle

Antworten:

197

Der Fehlercode EACCESbedeutet, dass Sie nicht über die erforderlichen Berechtigungen zum Ausführen von Anwendungen an diesem Port verfügen. Auf Linux-Systemen erfordert jeder Port unter 1024 Root-Zugriff.

Hexacyanid
quelle
5
Daher wird der sudo-Knoten myapp.js dies tun, wenn Sie die Berechtigung zur Verwendung von sudo haben (nur für Anfänger).
AlexMA
20
@ AlexMA, aber einen Server als Root zu betreiben ist ein großes Nein Nein
Patrick Evans
1
Wie führt man dann den Knoten auf Port 80 aus? Sollten Sie einfach ... nicht und einen Proxy verwenden?
AlexMA
9
@PatrickEvans Ich nehme an, die beste Vorgehensweise wäre, auf einem anderen Port zu laufen und einfach eine Portweiterleitungsregel einzurichten, wie hier erwähnt: stackoverflow.com/questions/16573668/…
AlexMA
73

Anstatt auf Port 80 ausgeführt zu werden, können Sie Port 80 mithilfe von auf den Port Ihrer Anwendung (> 1024) umleiten

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

Dies funktioniert, wenn Ihre Anwendung auf Port 3000 ausgeführt wird.

Kamrul
quelle
1
machte dies. Es wurde herausgefunden, dass Sie root sein müssen, um iptables in einer neuen Debian-Installation auszuführen, da sonst $ PATH nicht darauf verweist.
Brian Yeh
Ja, das war wahrscheinlich der einfachste Weg, dies zu tun. Ich bin auf Google Cloud Compute, was mir beim Berühren von Port 80 Probleme bereitete. Das war großartig. Vielen Dank.
Andy
Dies sollte die akzeptierte Lösung sein. Das Ausführen des Webservers als sudo ist gefährlich und gewährt einem Angreifer möglicherweise Root-Zugriff, wenn in der Anwendung eine Sicherheitsanfälligkeit vorliegt. Wenn die Anwendung Dateien erstellen würde, wären diese für andere Benutzer nicht zugänglich, sodass Sie sudonoch mehr verwenden können.
Jesusiniesta
Ich weiß nicht warum, aber unter Ubuntu 14.04 hat das bei mir nicht funktioniert. Ich benutze jetzt die Portweiterleitung über ssh, was genauso einfach ist. Ich habe unten eine Antwort gepostet .
Panepeter
19

Kurze Antwort: Sie können den Knotenzugriff auf diesen Port zulassen, indem Sie:

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

lange Antwort

Bearbeiten:

Funktioniert möglicherweise nicht mit neuen Knotenversionen

Reut Sharabani
quelle
Das hat funktioniert. @LinuxMint - sudo setcap 'cap_net_bind_service = + ep' / usr / local / bin / node
Kombiniere den
Manchmal ändert ein Update den Standortpfad zum Knoten, und dies funktioniert nicht mehr. Sie müssen es also erneut ausführen, um den neuen Pfad zum Knoten zu erhalten.
Steampowered
Es sieht aus wie diese nicht mehr funktionieren letzte Knoten Version 8. github.com/nodejs/node/issues/22648
timaw
6

Beachten Sie, dass Sie bei apacheAusführung einen Reverse-Proxy auf einem vhost erstellen können. Wenn Ihr Knoten auf Port ausgeführt wird 8080:

<VirtualHost 127.0.0.1:80>
        ServerName myLocalServer

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

Fügen Sie natürlich Server hinzu zu /etc/hosts:

127.0.0.1    myLocalServer

Sie müssen die entsprechenden Apache-Module aktivieren:

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

... und jetzt können Sie eine Verbindung herstellen http://myLocalServer.

Redsandro
quelle
3

Für diejenigen, die eine schnelle und einfache Lösung für eine Entwicklungsumgebung suchen , kann die Portweiterleitung über ssh eine gute Alternative sein:

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

Dadurch wird Port 80 auf localhost an Port 3000 auf localhost weitergeleitet.

Es muss als Root (privilegierter Port) ausgeführt werden. Um es abzubrechen, drücken Sie einfach Strg-C im Terminal. (Sie können das -fFlag hinzufügen , damit der Befehl im Hintergrund ausgeführt wird, aber dann müssen Sie ihn erneut finden, um ihn zu beenden.)

Für diese Lösung muss ein SSH-Server lokal ausgeführt werden . Dies ist schnell möglich . Beachten Sie jedoch die Auswirkungen auf die Sicherheit, wenn Sie sich in einem gemeinsam genutzten Netzwerk befinden. Möglicherweise möchten Sie mindestens eine zusätzliche Sicherheitsstufe anwenden (Kennwort und Root-Login deaktivieren).

Ich persönlich benutze dies immer nur auf meinem lokalen Computer. Ich bin mir nicht sicher, wie sich dies auf die Verarbeitungsgeschwindigkeit Ihrer Anforderungen auswirkt, wenn Sie dies in der Produktion ausführen. Vielleicht hat jemand eine Idee. Auf jeden Fall müssten Sie sicherstellen, dass dieser Befehl die ganze Zeit ausgeführt wird, was zu weiteren Kopfschmerzen führt. Für Produktionsumgebungen empfehle ich die Verwendung eines Reverse-Proxys wie Nginx .

Panepeter
quelle
2

Die Hexacyanid-Antwort ist richtig. Aber gibt es eine Lösung, damit dies funktioniert?

Die Antwort ist ja.

Wie?

Sie können reverse proxybeispielsweise einen nginx reverse proxyOn-Port ausführen 80und den Proxy an das Ziel übergeben ip:port, das der Knoten verwendet.

Sie können dies so einrichten, docker containerdass das Leben noch einfacher wird. Dies ist der offizielle Build von Nginx in Docker Hub, den Sie ziehen können.

Es gibt noch mehr Vorteile bei der Verwendung, reverse proxydass Sie es googeln können.

Ali_Hr
quelle
0

Ich habe den gleichen Fehler und habe versucht, meine Anwendung mit sudo auszuführen, und es hat bei mir funktioniert.

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

und mit sudo

mansi@mansi:~/NodePractice$ sudo node myFirst.js 
^C
Parth Pachchigar
quelle
... genau das wollen Sie nicht tun. Es entstehen Sicherheitsprobleme.
Bvdb
-1

Für die Verwendung von PORT 80 sind einige spezielle Berechtigungen erforderlich. Die Verwendung sudoder Anweisung der App vor dem Ausführen löste mein Problem. Wenn Sie beispielsweise npm zum Ausführen Ihrer App verwenden, können Sie Folgendes eingebensudo npm start

Webcrawler
quelle
1
Diese Antwort fügt nichts hinzu, um Inhalte zu beantworten, die bereits von anderen bereitgestellt wurden. Bitte antworten Sie nur, wenn Sie zusätzliche Informationen hinzufügen.
Brian Yeh
-2

Der Fehlercode EACCESbedeutet, dass Sie nicht über die erforderlichen Berechtigungen zum Ausführen von Anwendungen an diesem Port verfügen. Auf Linux-Systemen erfordert jeder Port unter 1024 Root-Zugriff.

Führen Sie das Programm mit sudoBerechtigung aus. Führen Sie den sudo suBefehl aus, bevor Sie das Programm ausführen.

Akshith Ranjan
quelle
Siehe die Post-Kommentare unter Hexacyanides-Antwort. Vielen Dank.
Brian Yeh