Wie kann ich mithilfe von setcap einen Remote-Port einrichten, der an Port 80 an meinen lokalen Host weitergeleitet wird?

11

Ich möchte Verbindungen für die Entwicklung kurz akzeptieren, wenn ich NATed bin, und deshalb versuche ich Folgendes:

$ ssh [email protected] -R 80:localhost:80

Was fehlschlägt, wenn ich versuche, einen zu niedrigen Port zu binden:

Warning: remote port forwarding failed for listen port 80

Also habe ich herausgefunden, dass ich es tun kann setcap 'cap_net_bind_service=+ep' /my/application, damit es Ports abhören kann, die niedriger als 1024 sind. Also habe ich das in meiner suders crontab:

@reboot setcap 'cap_net_bind_service=+ep' /usr/sbin/sshd

Aber es lässt mich immer noch nicht an Port 80 binden. Was mache ich falsch? Ich werde stattdessen nur Nginx als Proxy für 8080 oder Iptables oder ähnliches verwenden, aber ich bin immer noch neugierig, warum das, was ich versucht habe, nicht funktioniert hat.

Kit Sunde
quelle
Welches Dateisystem verwenden Sie? Nicht alle Dateisysteme unterstützen setcap.
Gilles 'SO - hör auf böse zu sein'
@ Gilles Ich verwende ext4, es ist das Standard-Ubuntu-Image von AWS und ich habe nichts Besonderes damit gemacht.
Kit Sunde
Es hört sich so an, als wären Sie root auf der Box. Vielleicht bin ich unwissend, sollte aber nicht einfach die erste Zeile als Root ausführen, um Ihr Problem zu lösen?
Christian
@Christian Sie können <1024 nicht ohne Absicht binden sudo. Zum Beispiel, wie man es nicht kann, apt-get install fooohne es vorher zu tun sudo.
Kit Sunde
@KitSunde Ja, root ist eine un-Ubuntuische Art zu sagen sudo. Es ist ein Benutzer, der über alle Berechtigungen verfügt, die ein normaler Benutzer nur erhält, wenn er dies tut sudo. root wird manchmal auch als Superuser bezeichnet. Im Grunde war meine Frage an Sie: Sie scheinen in der Lage zu sein, sudoauf der Box zu tun , warum können Sie in diesem Fall nicht?
Christian

Antworten:

13

OpenSSH lehnt die Bindung an privilegierte Ports ab, es sei denn, die Benutzer-ID des angemeldeten Benutzers lautet 0 (root). Die relevanten Codezeilen sind:

if (!options.allow_tcp_forwarding ||
    no_port_forwarding_flag ||
    (!want_reply && listen_port == 0) ||
    (listen_port != 0 && listen_port < IPPORT_RESERVED &&
    pw->pw_uid != 0)) {
        success = 0;
        packet_send_debug("Server has disabled port forwarding.");

Quelle: http://www.openssh.com/cgi-bin/cvsweb/src/usr.bin/ssh/serverloop.c?annotate=1.162 Zeilen 1092-1098

Wenn Sie neugierig sind, pwist vom Typ struct passwd *und unter Linux ist in definiert/usr/include/pwd.h

dwurf
quelle
Oh, das hatte ich nicht erwartet, das würde mit Sicherheit meine Frage beantworten.
Kit Sunde
2

Ich stoße auf ein ähnliches Problem, daher bestand die Lösung DNATdarin OUTPUT, der natTabellenkette eine Regel hinzuzufügen :

iptables -t nat -A OUTPUT -d 127.0.0.0/8 -p tcp --dport 80 \
-j DNAT --to-destination :8080

Diese Regel ersetzt effektiv den Zielport 80 durch 8080 für alle lokal erzeugten TCP-Pakete.

Wenn Sie auch die Weiterleitung eingehender Verbindungen zulassen möchten, fügen Sie der PREROUTING natKette eine zusätzliche Regel hinzu :

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

Wo 10.0.0.200ist die IP-Adresse der Schnittstelle, die eingehende Verbindungen an Ihren Webdienst weiterleiten soll?

Serge
quelle
1

Auf Client-Seite können Sie ssh über sudo ausführen:

sudo ssh -L 80:127.0.0.1:80 [email protected]

Es funktioniert, obwohl ich zugegebenermaßen nicht sicher bin, welche Auswirkungen die Sicherheit auf Ihr lokales System hat.

John Wilger
quelle
1

Dies ist ein großartiger Anwendungsfall für socat.

Führen Sie zunächst eine Remote-Weiterleitung an den Port 8080(oder einen anderen zulässigen Port) des Remote-Computers durch:

ssh [email protected] -R 8080:localhost:80

Ordnen Sie dann auf dem Remote-Computer Port 80zu Port zu 8080:

sudo socat TCP-LISTEN:80,fork TCP:localhost:8080

Anmerkungen:

Wie von Dirk Hoffman vorgeschlagen, können diese beiden Befehle in einer einzigen Zeile kombiniert werden:

ssh -t [email protected] -R 8080:localhost:80 sudo socat TCP-LISTEN:80,fork TCP:localhost:8080

(Dies -tist erforderlich, wenn Sie ein interaktives Terminal benötigen, um Ihr sudoPasswort einzugeben .)

Ben Mares
quelle
brillant! Liebe es!
Dirk Hoffmann
Es ist auch möglich, beide in einem Befehl wie folgt auszuführen: ssh -t -i ~ / .ssh / id_rsa -R 0.0.0.0:8080:0.0.0.0:8080 user @ remoteMachine - "sudo socat TCP-LISTEN: 80, fork TCP: localhost: 8080 "
Dirk Hoffmann
0

Sie können Ihren öffentlichen Schlüssel auch einfach zur Liste /root/.ssh/authorized_keys hinzufügen. Wenn Sie paranoid sind, sollten Sie das Ausführen von Befehlen als root wie folgt verbieten:

no-pty,no-agent-forwarding,no-X11-forwarding,command="/bin/noshell" ssh-rsa YOUR_PUBLIC_KEY 

Beachten Sie, dass für die Anmeldung als root möglicherweise "PermitRootLogin ohne Kennwort" in / etc / ssh / sshd_config hinzugefügt werden muss.

Moschops
quelle
0

Ausarbeitung des Lösungsvorschlags von Ben Mares oben,

unten ist ein Einzeiler, der:

öffnet zwei Remote-Ports vorwärts:
1. Remote-Port 8888 zum lokalen Port 80
2. Remote-Port 8443 zum lokalen Port 443

Auf dem Remotecomputer verbindet socat alles, was
an Port 80 ankommt, um an Port 8888 gestreamt zu werden,
   der dann an den lokalen Host-Port 80 getunnelt wird.
2. an Port 443 ankommt, um an Port 8443 gestreamt zu werden,
   der dann an lokalen Host-Port 443 getunnelt wird

ssh -t -i ~/.ssh/id_rsa \
    -R 0.0.0.0:8888:0.0.0.0:80 \
    -R 0.0.0.0:8443:0.0.0.0:443 \
    remoteUser@remoteMachine \
    -- "(sudo socat TCP-LISTEN:80,fork TCP:localhost:8888) & \
        sudo socat TCP-LISTEN:443,fork TCP:localhost:8443"

Wenn Sie den Befehl ausführen, müssen Sie Ihr Root-Passwort des Remotecomputers angeben (um an den Ports 80/443 auflisten zu können) und dann (solange der Tunnel eingerichtet ist) alles, was an Port 80 oder 443 ankommt des Remote-Hosts wird zu Ihren lokalen Computer-Ports 80 bzw. 443 getunnelt ...

merken!!

Um an alle Netzwerkschnittstellen (0.0.0.0) binden zu können, müssen Sie Ihre Remote-Computer bearbeiten /etc/ssh/sshd_configund GatewayPorts clientspecifiedoder einstellenGatewayPorts yes

Sie können dies auf dem Remote-Computer überprüfen, mit dem Folgendes angezeigt werden netstat -tlpn | grep -E '8888|8443'soll:

tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:8443            0.0.0.0:*               LISTEN      -

und nicht

tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:8443          0.0.0.0:*               LISTEN      -
Dirk Hoffmann
quelle