SSH-Tunnel erklärt: lokales, Remote- und dynamisches Port-Forwarding

SSH-Port-Forwarding gibt es in drei Arten. ssh -L öffnet einen Port auf Ihrem Rechner, der etwas auf der Seite des Servers erreicht. ssh -R öffnet einen Port auf dem Server, der etwas auf Ihrer Seite erreicht. ssh -D öffnet einen lokalen SOCKS-Proxy, der jede Verbindung über den Server schickt. Fügen Sie -N hinzu, um keinen Befehl auf dem Server auszuführen, und -o ExitOnForwardFailure=yes, damit ein Tunnel, der sich nicht öffnen lässt, mit einem Fehler endet.

Keine Lust, -L, -R und -D immer neu zu tippen? Wardterm speichert jeden Tunnel mit Server und Ports. Zeigen

Aktualisiert am . Alle Weiterleitungen, Bind-Adressen, GatewayPorts-Werte, AllowTcpForwarding-Werte und Fehlermeldungen wurden mit OpenSSH 10.3 unter macOS als Client gegen OpenSSH 10.0 unter Debian 13 ausgeführt, mit kleinen HTTP-Servern als Zielen. Mehrere -L-Optionen auf einer Verbindung, -L über -J und der Konfigurationsfehler bei einem Doppelpunkt in LocalForward wurden erneut mit OpenSSH 10.0 unter Debian 13 ausgeführt.

Welchen brauchen Sie?

OptionPort öffnet sich aufVerwenden Sie ihn, um
-L lokalIhrem Rechnereinen Dienst zu erreichen, den nur der Server erreicht, etwa eine Datenbank.
-R remotedem Serverden Server etwas auf Ihrem Rechner erreichen zu lassen, etwa eine Entwicklungsseite.
-D dynamischIhrem Rechnerim Web zu surfen oder sich mit vielen Hosts zu verbinden, als wären Sie auf dem Server.

Eine einfache Eselsbrücke: -L lauscht auf Ihrem lokalen Rechner, -R auf dem entfernten (remote) Server, und -D ist dynamisch, weil die Anwendung das Ziel jedes Mal selbst wählt.

Lokale Weiterleitung: -L

ssh -N -L 8080:localhost:80 user@server
your app -> your machine, port 8080 -> SSH -> server -> localhost:80 as seen by the server

Das Format ist lokaler_port:ziel:zielport. Jetzt zeigt http://127.0.0.1:8080 auf Ihrem Rechner den Webserver, der nur auf der eigenen Loopback-Adresse des Servers lauscht.

Entscheidend ist, dass der Server das Ziel auflöst. localhost bedeutet den Server selbst, nicht Ihren Rechner. Das Ziel kann auch ein anderer Host sein, den der Server erreicht, und dieser letzte Abschnitt wird von SSH nicht verschlüsselt:

ssh -N -L 8080:intranet.example.com:80 user@server

Remote-Weiterleitung: -R

ssh -N -R 9000:localhost:3000 user@server
a program on the server -> server, port 9000 -> SSH -> your machine -> localhost:3000 as seen by your machine

Jetzt kann ein Programm auf dem Server http://127.0.0.1:9000 öffnen und die App erreichen, die auf Ihrem Rechner läuft. Das funktioniert auch, wenn Ihr Rechner hinter NAT liegt, weil Ihre Seite die Verbindung aufgebaut hat.

Dynamische Weiterleitung: -D

ssh -N -D 1080 user@server
your app -> SOCKS proxy on your machine, port 1080 -> SSH -> server -> any host:port the app asks for

Richten Sie eine Anwendung, die SOCKS unterstützt, auf 127.0.0.1:1080. Zum Testen mit curl:

curl --socks5-hostname 127.0.0.1:1080 http://intranet.example.com/

--socks5-hostname lässt den Server die DNS-Abfrage machen, sodass interne Namen funktionieren und die Abfrage nicht aus Ihrem eigenen Netz nach außen dringt. Das einfache --socks5 löst den Namen auf Ihrem Rechner auf.

Browser-Einstellungen und DNS-Lecks behandelt SSH als SOCKS-Proxy nutzen.

Mehrere Ports oder über einen Jump-Host

Wiederholen Sie die Option, um mehrere Weiterleitungen über eine Verbindung zu öffnen:

ssh -N -L 127.0.0.1:8080:localhost:80 -L 127.0.0.1:5433:localhost:5432 user@server

Steht der Server hinter einem Bastion-Host, fügen Sie -J hinzu. Die Weiterleitung beginnt am letzten Server der Kette, also löst dieser Server das Ziel auf:

ssh -N -J user@bastion -L 127.0.0.1:5433:localhost:5432 user@db-server

Ketten von Servern erklärt ProxyJump und Jump-Hosts in SSH nutzen.

Einen Tunnel ohne Shell betreiben

  • -N führt keinen Befehl auf dem Server aus. Die Sitzung trägt nur den Tunnel.
  • -f wechselt nach der Anmeldung in den Hintergrund, sodass Sie vorher noch eine Passphrase tippen können.
  • -o ExitOnForwardFailure=yes beendet sich mit einem Fehler, wenn die Weiterleitung nicht eingerichtet werden kann.
ssh -f -N -o ExitOnForwardFailure=yes -L 127.0.0.1:8080:localhost:80 user@server

Ohne ExitOnForwardFailure gibt ssh eine Warnung aus und bleibt ohne funktionierenden Tunnel verbunden, was in einem Skript verwirrend ist. Mit der Option endet ein bereits belegter lokaler Port mit Exit-Code 255 und Could not request local forwarding, und ein belegter Remote-Port mit remote port forwarding failed for listen port.

Ein Haken aus unseren Tests: Bei einem einfachen -L 8080:... lauscht ssh sowohl auf 127.0.0.1 als auch auf ::1. Ist nur eine davon belegt, zum Beispiel durch ein anderes Programm auf IPv4, gibt ssh bind [127.0.0.1]:8080: Address already in use aus und läuft auch mit ExitOnForwardFailure=yes weiter. Ihre App erreicht dann womöglich dieses andere Programm. Schreiben Sie die Adresse hin, wie in -L 127.0.0.1:8080:..., wird daraus ein echter Fehler, nutzen Sie diese Form also in Skripten.

Um einen Tunnel im Hintergrund zu beenden, suchen Sie seinen Prozess und beenden ihn:

pgrep -f 'L 127.0.0.1:8080'
kill PID

Tunnel, die Sie oft starten, stoppen Sie mit einem Control-Socket einfach per Name, mit ssh -O exit. Siehe SSH-Tunnel speichern, starten und stoppen.

Um einen Tunnel in Ihrer Konfiguration zu halten, verwenden Sie LocalForward, RemoteForward und DynamicForward:

Host dbtunnel
  HostName 203.0.113.10
  User user
  LocalForward 127.0.0.1:8080 localhost:80
  ExitOnForwardFailure yes

Nur an localhost binden

Ein weitergeleiteter Port ist für jeden offen, der ihn erreichen kann, und der Dienst dahinter vertraut womöglich Verbindungen vom Server. Standardmäßig bindet ssh nur an Loopback, belassen Sie es dabei, wenn Sie keinen Grund dagegen haben.

Diese Befehle öffnen den lokalen Port für Ihr ganzes Netz. Wir haben bestätigt, dass beide auf allen Schnittstellen lauschen:

ssh -N -L 0.0.0.0:8080:localhost:80 user@server
ssh -N -g -L 8080:localhost:80 user@server

Bei -R entscheidet der Server, mit GatewayPorts in seiner sshd-Konfiguration:

GatewayPorts-R 9000:...-R 0.0.0.0:9000:...
no (Standard)Nur LoopbackNur Loopback, ohne Fehler
clientspecifiedNur LoopbackAlle Schnittstellen
yesAlle SchnittstellenAlle Schnittstellen, und 127.0.0.1:9000 öffnet sich ebenfalls auf allen Schnittstellen

Ist Ihr -R-Port von außen nicht erreichbar, ist GatewayPorts also der übliche Grund. Einen Dienst Ihres Laptops auf diese Weise im Internet freizugeben, ist selten das, was Sie wollen. Bevorzugen Sie clientspecified, wenn Sie es brauchen, und fügen Sie eine Firewall-Regel hinzu.

Wenn der Server ablehnt

AllowTcpForwarding in der sshd-Konfiguration des Servers steuert das. Die Werte sind yes (Standard), no, local (erlaubt -L und -D) und remote (erlaubt -R).

  • Ein blockiertes -L oder -D verbindet ohne Probleme. Der Fehler kommt erst, wenn etwas den Port nutzt: channel 2: open failed: administratively prohibited: open failed.
  • Ein blockiertes -R meldet remote port forwarding failed for listen port.

Die Handbuchseite weist darauf hin, dass das Abschalten der Weiterleitung wenig bringt, wenn Benutzer auch eine Shell haben, da sie einen eigenen Forwarder ausführen können. Um jemanden wirklich einzuschränken, nehmen Sie auch die Shell weg, wie bei einem reinen Tunnel-Benutzer für eine Datenbank.

Zwei weitere Fehler kommen oft vor. Ist der lokale oder entfernte Port belegt, hilft Address already in use und remote port forwarding failed. Werden Verbindungen durch den Tunnel abgelehnt, hilft administratively prohibited: open failed.

Fragen

Was ist der Unterschied zwischen ssh -L und ssh -R?

-L öffnet einen Port auf Ihrem Rechner, der zu etwas führt, das der Server erreicht. -R öffnet einen Port auf dem Server, der zurück zu etwas auf Ihrem Rechner führt.

Wie leite ich mehrere Ports mit einem ssh-Befehl weiter?

Wiederholen Sie die Option: ssh -N -L 127.0.0.1:8080:localhost:80 -L 127.0.0.1:5433:localhost:5432 user@server. Eine Verbindung trägt alle Weiterleitungen. In ~/.ssh/config schreiben Sie eine LocalForward-Zeile pro Port.

Wie halte ich einen SSH-Tunnel dauerhaft offen?

Starten Sie ihn mit -N und -o ExitOnForwardFailure=yes, und lassen Sie autossh oder einen systemd-Dienst ihn nach einem Abbruch neu starten. Siehe autossh und systemd.

Warum verbindet der Tunnel, aber nichts funktioniert?

Der Server kann Weiterleitungen mit AllowTcpForwarding verbieten. Ein gesperrtes -L oder -D verbindet trotzdem und scheitert erst bei Nutzung des Ports, mit administratively prohibited: open failed.

Ist SSH-Port-Forwarding sicher?

Der Verkehr ist zwischen Ihrem Rechner und dem SSH-Server verschlüsselt. Der Abschnitt vom Server zum Ziel ist es nicht, und einen Port, der auf 0.0.0.0 lauscht, kann jeder in Ihrem Netzwerk nutzen. Lassen Sie die Listen-Adresse daher auf 127.0.0.1.

Quellen

Mehr zu Tunnel und Jump-Hosts

Alle Anleitungen