Frage Wie führe ich einen Server auf Port 80 als normaler Benutzer unter Linux aus?


Ich habe lange darüber gegoogelt, konnte es aber nicht finden.

Ich bin auf Ubuntu Linux und möchte einen Server auf Port 80 laufen lassen, aber aufgrund des Sicherheitsmechanismus von Ubuntu bekomme ich den folgenden Fehler:

java.net.BindException: Berechtigung verweigert: 80

Ich denke, es sollte einfach genug sein, diesen Sicherheitsmechanismus entweder zu deaktivieren, so dass Port 80 für alle Benutzer verfügbar ist, oder dem aktuellen Benutzer die erforderlichen Berechtigungen zuzuweisen, um auf Port 80 zuzugreifen.


281
2017-11-10 14:31


Ursprung


Was ist das Problem, wenn der Server auf einem anderen Port ausgeführt wird, der nicht privilegiert ist? Sie denken über etwas so hartes nach, wie den Sicherheitsmechanismus zu deaktivieren, ohne zumindest einen sehr ernsten Grund für die Ausführung eines Servers an diesem Port zu liefern. Ist der Server fest an Port 80 gebunden? Wenn ja, wirf es weg. - Anonymous
Oder eine Python-Fehlermeldung: socket.error: [Errno 13] Permission denied - Kazark
mögliches Duplikat von Normaler Benutzer mit Ports unter 1024 - Roman
Du kannst nicht. Ports unter 1024 sind privilegiert, und nur Root kann auf ihnen abhörende Sockets öffnen. Es empfiehlt sich, die Berechtigungen nach dem Öffnen zu löschen. - Falcon Momot
"Anonymous" - die Benutzer in der Welt wurden geschult, bestimmte Dienste in bestimmten Häfen zu suchen. In einigen Fällen wurde es standardisiert. Zum Beispiel HTTP auf Port 80 und HTTPS auf Port 443. Es ist schwer, die Benutzer und Standards der Welt zu ändern. - jww


Antworten:


Kurze Antwort: Sie können nicht. Ports unter 1024 können nur von root geöffnet werden. Wie Kommentar - nun, Sie können, mit CAP_NET_BIND_SERVICE, aber dieser auf java bin angewendete Ansatz macht jedes Java-Programm, das mit dieser Einstellung ausgeführt werden soll, was unerwünscht ist, wenn nicht ein Sicherheitsrisiko.

Die lange Antwort: Sie können Verbindungen auf Port 80 zu einem anderen Port umleiten, den Sie als normaler Benutzer öffnen können.

Als root ausführen:

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

Da Loopback-Geräte (wie localhost) nicht die Prerouting-Regeln verwenden, wenn Sie localhost usw. verwenden müssen, fügen Sie auch diese Regel hinzu (Danke @Francesco):

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

HINWEIS: Die obige Lösung ist nicht gut geeignet für Mehrbenutzersysteme, da jeder Benutzer den Port 8080 (oder einen anderen hohen Port, den Sie verwenden möchten) öffnen und so den Datenverkehr abfangen können. (Anerkennung an CesarB).

EDIT: wie per Kommentar Frage - um die oben genannte Regel zu löschen:

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

Dies wird etwas ausgeben wie:

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

Die Regel, an der Sie interessiert sind, ist Nr. 2, um es zu löschen:

# iptables -t nat -D PREROUTING 2

330
2017-11-10 14:41



@Sunny: upvotes sind nicht für die schnellste Waffe im Westen, aber für die besten Antworten. Deines ist das Beste bis jetzt (ich habe nur iptables erwähnt; du hast tatsächlich die volle Befehlszeile angegeben). Das einzige, was mir gehört, ist nicht der Vorbehalt, dass andere Benutzer auch an Port 8080 binden können. - CesarB
Beachten Sie, dass dies nicht mit IPv6 funktioniert. - Emmanuel Bourg
Kann jemand erklären, wie ich diese Regel später entfernen kann, wenn ich will? Nach dem Ausführen funktioniert es, aber es ist anscheinend keine "Regel", weil es nicht angezeigt wird, wenn ich es tue sudo iptables --list. Ich weiß, was Iptables ist und tut, aber ich habe es vorher nie wirklich benutzt. - Encoderer
Danke für deine Antwort ... wenn ich Ubuntu neu starte, verschwindet diese Regel und ich muss sie erneut ausführen. Gibt es eine Möglichkeit, es für immer zu speichern? - Coderji
@Coderji: Überprüfen Sie den Abschnitt "Speichern" in der Community-Dokumentation: help.ubuntu.com/community/IptablesHowTo - Sunny


Benutzen authbind.

Es funktioniert sogar mit Java, wenn Sie den IPv4-only-Stack von Java aktivieren. Ich benutze:

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

77
2017-11-14 13:12



Wenn der Server Tomcat ist, können Sie authbind automatisch verwenden, indem Sie festlegen AUTHBIND=yes in / etc / default / tomcat6 - Emmanuel Bourg
Ich konnte es nicht mit dem Standard-Java-Paket auf Ubuntu-Server arbeiten ... - Ashley Steel
Mir auch keine bekannte Lösung? - mark
Beachten Sie, dass Sie konfigurieren müssen authbind um dies tatsächlich zuzulassen. Von der man-Seite: "/ etc / authbind / byport / port ist getestet. Wenn diese Datei dem anrufenden Benutzer gemäß Zugriff (2) zur Ausführung zugänglich ist, ist die Bindung an den Port autorisiert.", z.B. für Port 80, sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80. Die Erstinstallation von authbind hat in der Regel keine vorkonfigurierten Berechtigungen. - Jason C
Oh nonononononono, niemals chmod 777 irgendwas! - Johannes


Wenn Ihr System dies unterstützt, können Sie möglicherweise Funktionen verwenden. Siehe man Fähigkeiten, die Sie benötigen, wäre CAP_NET_BIND_SERVICE.

Auf neueren Debian / Ubuntu können Sie ausführen:

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

45
2018-05-30 20:32



das funktioniert für nodejs: setcap 'cap_net_bind_service = + ep' / usr / bin / nodejs - JasonS
Diese. Ich frage mich, warum diese Antwort nicht mehr Upvotes hat. Viel einfacher als die iptables Option imho. - Dominik R
Dies ist die richtige und effizienteste Antwort, alle anderen Antworten verursachen einen Leistungseinbruch oder sind nur unsicher / unsicher. - OneOfOne


Eine andere Lösung besteht darin, die App setuid so zu konfigurieren, dass sie mit Port 80 binden kann. Führen Sie als root Folgendes aus

chown root ./myapp
chmod +S ./myapp

Denken Sie daran, dass dies zu potenziellen Sicherheitslücken führen kann, wenn es nicht absolut korrekt durchgeführt wird, da Ihre App mit dem Netzwerk kommuniziert und mit vollständigen Root-Rechten ausgeführt wird. Wenn Sie diese Lösung verwenden, sollten Sie den Quellcode für Apache oder Lighttpd oder etwas Ähnliches betrachten, wo sie die root-Rechte verwenden, um den Port zu öffnen, aber dann sofort diese privs aufgeben und so zu einem Benutzer mit niedrigeren Rechten werden Ein Hijacker kann nicht den ganzen Computer übernehmen.

Update: Wie in gesehen diese Fragescheint es, dass Linux-Kernel seit 2.6.24 eine neue Fähigkeit haben, die es Ihnen erlaubt, eine ausführbare Datei (aber natürlich kein Skript) als "CAP_NET_BIND_SERVICE"Fähigkeit. Wenn Sie das Debian-Paket" libcap2-bin "installieren, können Sie das tun, indem Sie den Befehl absetzen

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

39
2017-11-10 14:44



Das ist dasselbe wie das Ausführen als root, es sei denn, die App weiß, wie man Privilegien löscht. - CesarB
Das ist gefährlich. Dies bedeutet, dass jede Anfrage als root ausgeführt wird. Es ist aus einem Grund, dass sogar Apache als root zu binden beginnt, und dann die Berechtigungen an einen anderen Benutzer ablegt. - Sunny
Paul: Die iptables sind nicht so gefährlich, denn selbst wenn die App kompromittiert ist, wird sie das System nicht bei Angriffen aussetzen, zumindest nicht mit root-Rechten. Das Ausführen der App als root ist eine andere Geschichte. - Sunny
Die Gefahr für iptables besteht nur, wenn es sich um ein Mehrbenutzer-System handelt, wie CesarB sagte, da jeder an 8080 binden und den Verkehr abfangen kann. - Sunny
lol, liebe, wie die akzeptierte Antwort eine -15 hat - Evan Teran


Vorgehensweise vorgeschlagen von Sunny und CesarB:

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

funktioniert gut, aber es hat einen kleinen Nachteil - es verhindert nicht, dass Benutzer direkt an Port 8080 statt 80 anschließen.

Stellen Sie sich das folgende Szenario vor, wenn dies ein Problem sein kann.

Nehmen wir an, wir haben einen Server, der HTTP-Verbindungen an Port 8080 und HTTPS-Verbindungen an Port 8181 akzeptiert.

Wir verwenden iptables, um die folgenden Umleitungen einzurichten:

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

Angenommen, unser Server entscheidet, Benutzer von einer HTTP-Seite auf eine HTTPS-Seite umzuleiten. Wenn wir die Antwort nicht sorgfältig umschreiben, würde sie zu Redirect umleiten https://host:8181/. An dieser Stelle sind wir geschraubt:

  • Einige Benutzer würden das Lesezeichen setzen https://host:8181/ URL und diese URL müssen beibehalten werden, um zu vermeiden, dass ihre Lesezeichen beschädigt werden.
  • Andere Benutzer können keine Verbindung herstellen, da ihre Proxyserver keine nicht standardmäßigen SSL-Ports unterstützen.

Ich benutze den folgenden Ansatz:

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

In Kombination mit der Standardregel REJECT in der Kette INPUT verhindert dieser Ansatz, dass Benutzer direkt eine Verbindung zu den Ports 8080, 8181 herstellen


35
2018-02-20 16:19



Das ist gut, aber warum binden Sie den Daemon nicht nur an localhost: 8080 statt an 0.0.0.0:8080? Ich will das machen, aber dafür brauche ich die iptables. - Amala
Es funktioniert, wirklich cool. - xtian


Ich benutze einfach Nginx vorne. Es kann auch auf localhost ausgeführt werden.

  • apt-get install nginx

.. oder ..

  • pkg_add -r nginx 

.. oder was immer zu Ihrem Betriebssystem passt.

Alles, was Sie in nginx.conf benötigen, wenn es auf localhost läuft, ist:

Server {
        höre 80 zu;
        Servername some.domain.org;
        Standort / {
            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



Ich mag diese Lösung wirklich. - thomasfedb
Dies ist (eine der) von JFrog selbst vorgeschlagene Lösung: jfrog.com/confluence/display/RTF/nginx - stolsvik


Traditionell unter Unix kann nur root an niedrige Ports (<1024) binden.

Die einfachste Möglichkeit, dies zu umgehen, besteht darin, den Server auf einem Server auszuführen hoch Port (zum Beispiel 8080) und verwenden Sie eine einfache iptables-Regel, um die Verbindungen von Port 80 zu Port 8080 weiterzuleiten. Beachten Sie, dass Sie damit den zusätzlichen Schutz vor den niedrigen Ports verlieren; Jeder Benutzer auf Ihrem Computer kann an Port 8080 binden.


29
2017-11-10 14:36