SSH-Tunnel einrichten: Port-Forwarding mit -L, -R und -D erklärt
Ein SSH-Tunnel leitet den Datenverkehr eines TCP-Ports durch eine verschlüsselte SSH-Verbindung an einen anderen Rechner weiter (Port-Forwarding). Mit ssh -L machen Sie einen entfernten Dienst über einen lokalen Port erreichbar, mit -R öffnen Sie einen Port auf dem Server, der zu Ihrem Rechner führt, und mit -D startet ssh einen SOCKS-Proxy. Voraussetzung ist ein SSH-Zugang, dessen Server Weiterleitungen erlaubt.
Nach dem Wikipedia-Artikel zu Secure Shell lassen sich über SSH beliebige TCP/IP-Verbindungen tunneln, und ein SSH-Client kann sich wie ein SOCKS-Server verhalten. Verschlüsselt ist die Strecke zwischen ssh-Client und SSH-Server. Die letzte Etappe vom Server zum Ziel baut der Server als eigene TCP-Verbindung auf, sie läuft nicht mehr durch den Tunnel.
Lokal, entfernt, dynamisch: die drei Varianten
| Option | Wo lauscht ein Port? | Wohin führt die Verbindung? | Typischer Einsatz |
|---|---|---|---|
-L (lokal) | auf Ihrem Rechner | zu host:port, aufgebaut vom Server aus | Datenbank oder interne Webseite hinter einer Firewall |
-R (entfernt) | auf dem Server | zu einem Ziel, das Ihr Rechner erreicht, etwa localhost:3000 | lokalen Dienst vom Server aus erreichbar machen |
-D (dynamisch) | auf Ihrem Rechner | zu jedem Ziel, das die Anwendung per SOCKS4 oder SOCKS5 nennt | Anwendungen mit SOCKS-Unterstützung, etwa curl, über den Server leiten |
Bei -L und -D bindet ssh den lokalen Port standardmäßig an die Loopback-Adresse, sodass nur Ihr eigener Rechner ihn nutzen kann. Im Protokoll sind das zwei Kanaltypen: direct-tcpip für lokale und forwarded-tcpip für entfernte Weiterleitungen (RFC 4254, Abschnitt 7).
-L: eine Datenbank hinter der Firewall erreichen
Eine PostgreSQL-Datenbank (Standardport 5432) ist nur vom Server bastion.example.org aus erreichbar. So holen Sie sie auf Ihren Rechner:
- Tunnel aufbauen:
ssh -N -L 5433:db.example.org:5432 benutzer@bastion.example.org. Der Tunnel besteht, solange dieser ssh-Prozess läuft. - In einem zweiten Terminal mit dem lokalen Port verbinden:
psql -h localhost -p 5433 -U dbbenutzer meinedb.
Die Angabe 5433:db.example.org:5432 besteht aus lokalem Port, Zielhost und Zielport. Der lokale Port ist frei wählbar, 5433 kollidiert nur nicht mit einem lokal laufenden PostgreSQL auf 5432. Dasselbe Muster gilt für jeden TCP-Dienst hinter dem Server, etwa eine interne Webseite: -L 8443:intranet.example.org:443. Das Ziel spricht der Server an: Steht dort localhost, ist der Server selbst gemeint, nicht Ihr Rechner. Die Option -N führt keinen Befehl auf dem Server aus und eignet sich laut Handbuch, wenn nur Ports weitergeleitet werden sollen.
-R und -D: Rückwärtstunnel und SOCKS-Proxy
Ein entfernter Tunnel kehrt die Richtung um:
ssh -N -R 8080:localhost:3000 benutzer@server.example.org
Auf dem Server lauscht nun Port 8080, und jede Verbindung dorthin läuft durch den Tunnel zu Port 3000 auf Ihrem Rechner. Der Server bindet diesen Port standardmäßig nur an die Loopback-Schnittstelle. Eine andere Bind-Adresse funktioniert nur, wenn GatewayPorts in der Serverkonfiguration aktiviert ist.
Der dynamische Tunnel braucht kein festes Ziel:
ssh -N -D 1080 benutzer@server.example.org
curl --socks5-hostname localhost:1080 https://example.org/
ssh spricht dann SOCKS4 und SOCKS5, das Ziel nennt die Anwendung, die Verbindung baut der Server auf. Mit --socks5-hostname löst der Proxy den Hostnamen auf, nicht Ihr Rechner.
Im Hintergrund, mit Fehlerprüfung und über einen Sprungserver
| Option | Wirkung laut OpenSSH-Handbuch |
|---|---|
-N | kein Befehl auf dem Server, entspricht SessionType none |
-f | ssh geht kurz vor der Befehlsausführung in den Hintergrund, praktisch, wenn vorher ein Passwort oder eine Passphrase abgefragt wird |
-o ExitOnForwardFailure=yes | ssh beendet die Verbindung, wenn eine Weiterleitung nicht eingerichtet werden kann, etwa weil der Port belegt ist (Standard: no) |
-J benutzer@sprung | verbindet zuerst zum Sprungserver und baut von dort die Verbindung zum Ziel auf, mehrere Hops mit Komma getrennt |
Ein Tunnel im Hintergrund, der nicht ohne Weiterleitung weiterläuft, wenn der lokale Port belegt ist:
ssh -fN -o ExitOnForwardFailure=yes -L 5433:db.example.org:5432 benutzer@bastion.example.org
Sauber beenden lässt sich ein Hintergrund-Tunnel, wenn ssh als Master mit Kontrollsocket startet und Sie ihm später -O exit schicken:
ssh -fN -M -S ~/.ssh/db.sock -L 5433:db.example.org:5432 benutzer@bastion.example.org
ssh -S ~/.ssh/db.sock -O exit benutzer@bastion.example.org
Dauerhaft gehört das Ganze in ~/.ssh/config. Dort legen Sie den Sprungserver per ProxyJump fest. Einstellungen für den Sprungserver selbst gehören ebenfalls in diese Datei, denn Optionen von der Kommandozeile gelten laut Handbuch in der Regel nur für das Ziel:
Host db-tunnel
HostName bastion.example.org
User benutzer
ProxyJump benutzer@sprung.example.org
LocalForward 5433 db.example.org:5432
ExitOnForwardFailure yes
Gestartet wird er mit ssh -N db-tunnel.
Auf dem Server einschränken und Risiken begrenzen
Einstellung in sshd_config | Wirkung und Standard |
|---|---|
AllowTcpForwarding | Standard yes. Weitere Werte: no, local (nur lokale Weiterleitung) und remote (nur entfernte Weiterleitung) |
GatewayPorts | Standard no: entfernte Weiterleitungen lauschen nur auf Loopback. yes bindet an alle Adressen, clientspecified lässt den Client wählen |
PermitOpen | erlaubte Ziele als host:port, any oder none. Standardmäßig ist alles erlaubt |
PermitListen | Adressen und Ports, auf denen eine entfernte Weiterleitung lauschen darf. Standardmäßig ist alles erlaubt |
DisableForwarding | schaltet alle Weiterleitungen ab, auch X11 und Agent, und überschreibt die übrigen Optionen |
Diese Optionen dürfen in einem Match-Block stehen, also nur für bestimmte Benutzer gelten. Dazu die Warnung aus dem Handbuch: Wer AllowTcpForwarding no setzt, verbessert die Sicherheit nur, wenn den Benutzern auch die Shell verwehrt wird, denn sonst können sie jederzeit eigene Weiterleitungsprogramme installieren. Einen Schlüssel nur für einen Tunnel schränken Sie in authorized_keys ein:
restrict,port-forwarding,permitopen="db.example.org:5432",command="echo Nur Tunnel" ssh-ed25519 AAAA... notebook
restrict schaltet Port-, Agent- und X11-Weiterleitung sowie das Terminal ab, port-forwarding erlaubt Port-Weiterleitung wieder, permitopen begrenzt -L auf genau dieses Ziel, und command ersetzt jeden vom Benutzer gewünschten Befehl. Dabei vergleicht permitopen den Hostnamen buchstäblich, ohne Mustervergleich und ohne Namensauflösung. Entfernte Tunnel begrenzt permitlisten, ganz verbieten lassen sie sich mit AllowTcpForwarding local.
- Zu offene Ports:
-g, ein Stern als Bind-Adresse oderGatewayPorts yes(auf Client- oder Serverseite) lassen andere Rechner auf den Tunnelport zugreifen. - Zu großzügige Voreinstellung: Standardmäßig sind Weiterleitungen zu allen Zielen erlaubt, die der Server erreicht.
- Firewall-Umgehung: Die Wikipedia nennt das Umgehen einer Firewall als Beispiel für den SOCKS-Modus. In Firmennetzen klären Sie Tunnel deshalb vorher mit der IT.
Das deutsche Bundesamt für Sicherheit in der Informationstechnik (BSI) empfiehlt in der Richtlinie TR-02102-4 (Fassung 2026-01) die Protokollversion SSH-2, SSH-1 wird wegen kryptographischer Schwächen nicht empfohlen. Port-Weiterleitungen regelt die Richtlinie nicht, sie enthält keine Konfigurationsanleitungen für konkrete Implementierungen. Das bleibt Ihre Entscheidung in sshd_config.
Häufige Fragen
Was ist ein SSH-Tunnel?
Ein SSH-Tunnel (Port-Forwarding) leitet den Verkehr eines TCP-Ports durch eine verschlüsselte SSH-Verbindung zu einem anderen Rechner. Verschlüsselt ist die Strecke zwischen ssh-Client und SSH-Server, das Ziel erreicht der Server mit einer normalen Verbindung.
Was ist der Unterschied zwischen ssh -L, -R und -D?
Bei -L lauscht ein lokaler Port und die Verbindung geht vom Server zu host:port. Bei -R lauscht der Server und leitet zu Ihrem Rechner. Bei -D lauscht ein lokaler Port als SOCKS-Proxy, das Ziel nennt die Anwendung.
Wofür brauche ich -N und -f bei ssh?
Mit -N führt ssh keinen Befehl auf dem Server aus und leitet nur Ports weiter. Mit -f wechselt ssh kurz vor der Befehlsausführung in den Hintergrund. Zusammen mit ExitOnForwardFailure=yes bricht ssh ab, wenn eine Weiterleitung scheitert.
Wie schränke ich SSH-Tunnel auf dem Server ein?
In sshd_config steuern AllowTcpForwarding, GatewayPorts, PermitOpen und PermitListen die Weiterleitung, DisableForwarding schaltet sie ab. Pro Schlüssel begrenzen permitopen und permitlisten in authorized_keys die Ziele.
Wie funktioniert ssh -J mit einem Sprungserver?
ssh -J baut zuerst eine Verbindung zum Sprungserver auf und stellt von dort eine TCP-Weiterleitung zum eigentlichen Ziel her. Mehrere Hops trennen Sie mit Kommas. Optionen von der Kommandozeile gelten in der Regel nur für das Ziel.
- OpenSSH: ssh(1), Optionen -L, -R, -D, -N, -f, -J
- OpenSSH: ssh_config(5), LocalForward, GatewayPorts, ProxyJump
- OpenSSH: sshd_config(5), AllowTcpForwarding, PermitOpen
- OpenSSH: sshd(8), authorized_keys, permitopen und restrict
- BSI: Technische Richtlinie TR-02102-4, Verwendung von Secure Shell (SSH)
- RFC 4254: The Secure Shell (SSH) Connection Protocol, Abschnitt 7
Weitere Anleitungen

Docker Compose Grundlagen: compose.yaml, Befehle und typische Fehler
Docker Compose erklärt: Aufbau der compose.yaml, Beispiel mit WordPress und MariaDB, Befehle wie up, down und logs, .env-Variablen und typische Fehler.

SSH-Schlüssel erstellen mit ssh-keygen: Ed25519, Passphrase und Server-Zugang
SSH-Schlüssel erstellen mit ssh-keygen: Ed25519, ECDSA oder RSA, Passphrase, ssh-agent, Kopie auf den Server, Dateirechte sowie Windows und macOS.