Reverse-SSH-Tunnel einrichten, um einen Rechner hinter NAT zu erreichen

Führen Sie auf dem Rechner hinter NAT ssh -N -R 2222:localhost:22 user@server aus, wobei server eine öffentliche Adresse hat. Auf diesem Server erreichen Sie den versteckten Rechner dann mit ssh -p 2222 user@localhost. Der Port lauscht standardmäßig nur auf dem Loopback des Servers und ist daher nicht aus dem Internet erreichbar, solange Sie GatewayPorts nicht ändern.

Keine Lust, die -R-Optionen jedes Mal neu zu tippen? Wardterm speichert den Tunnel einmal und öffnet ihn, wenn Sie ihn brauchen. Zeigen

Aktualisiert am . OpenSSH-10.0-Client und -Server unter Debian 13 in Wegwerf-Containern im selben Netz, wobei ein Container den Rechner hinter NAT spielte.

So funktioniert es

Ein Rechner hinter NAT kann keine eingehenden Verbindungen annehmen, aber er kann ausgehende aufbauen. Er verbindet sich also nach außen mit einem Server mit öffentlicher Adresse und bittet diesen, auf einem Port zu lauschen. Verbindungen zu diesem Port laufen über die bestehende SSH-Verbindung zurück.

Die beiden anderen Arten der Weiterleitung erklärt lokale, entfernte und dynamische SSH-Tunnel.

Per SSH auf den versteckten Rechner

Der versteckte Rechner braucht einen eigenen laufenden SSH-Server. Auf dem versteckten Rechner:

ssh -N -o ExitOnForwardFailure=yes -R 2222:localhost:22 user@server

-N führt keinen Befehl auf der Gegenseite aus. -R 2222:localhost:22 bedeutet, dass Port 2222 auf dem Server zu Port 22 auf diesem Rechner führt. Mit -f läuft es im Hintergrund.

Auf dem Server sehen Sie den Port und können ihn nutzen:

$ ss -ltn | grep 2222
LISTEN 0  128  127.0.0.1:2222  0.0.0.0:*
LISTEN 0  128      [::1]:2222     [::]:*
$ ssh -p 2222 hiddenuser@localhost

Von Ihrem Laptop aus gehen Sie in einem Schritt über den Server:

ssh -J user@server -p 2222 hiddenuser@localhost

Damit sich die Host-Schlüssel nicht vermischen, denn localhost kann viele Rechner meinen, tragen Sie dies in ~/.ssh/config ein:

Host home
  HostName localhost
  Port 2222
  User hiddenuser
  ProxyJump user@server
  HostKeyAlias home

Eine lokale Web-App zeigen

ssh -N -R 8080:localhost:3000 user@server

Jetzt erreicht curl http://localhost:8080/ auf dem Server den Port 3000 Ihres Rechners. In unserem Test wurde curl http://server:8080/ von einem anderen Rechner aus abgelehnt, bis wir GatewayPorts geändert haben.

Bei Port 0 wählt der Server einen freien Port, und ssh gibt ihn aus:

$ ssh -N -R 0:localhost:3000 user@server
Allocated port 33341 for remote forward to localhost:3000

GatewayPorts: wer den Port erreicht

Diese Einstellung steht in der sshd_config des Servers und steht standardmäßig auf no. Das haben wir gemessen:

GatewayPorts-R 8080:...-R 0.0.0.0:8080:...
noNur LoopbackNur Loopback, die Adresse wird ignoriert
clientspecifiedNur LoopbackAlle Adressen, von anderen Rechnern erreichbar
yesAlle AdressenAlle Adressen

Mit yes lauschte in unserem Test sogar -R localhost:8080:... auf allen Adressen. Brauchen Sie Zugriff von außen, überlässt clientspecified dem Client die Wahl, und die Firewall muss den Port weiterhin erlauben.

Privat halten

  • Lassen Sie GatewayPorts no und nutzen Sie -J wie oben gezeigt. Dann erreicht den Port nur, wer sich am Server anmelden kann.
  • Denken Sie an die anderen Benutzer auf dem Server. Den Loopback teilen alle, die dort angemeldet sind. Sie können den Port erreichen, und der Dienst dahinter braucht trotzdem seine eigene Anmeldung.
  • Verwenden Sie für den Tunnel einen eigenen Schlüssel und ein eigenes Konto, denn der Rechner hinter NAT behält einen Schlüssel, mit dem man sich an Ihrem Server anmelden kann. Die autossh-Anleitung zeigt eine getestete, eingeschränkte Konfiguration.

Wenn der Port belegt ist

Mit ExitOnForwardFailure=yes bricht ssh ab und beendet sich mit Code 255:

Error: remote port forwarding failed for listen port 2222

Ohne diese Option erhalten Sie nur eine Warning, und ssh bleibt ohne Tunnel verbunden, was leicht übersehen wird. Eine häufige Ursache ist eine alte Verbindung, die den Port auf dem Server noch belegt. AllowTcpForwarding no oder eine PermitListen-Regel auf dem Server führt zu demselben Fehler.

Dauerhaft laufen lassen

Ein einfaches ssh -R endet, wenn die Verbindung abbricht, und nichts startet es neu. Für einen dauerhaften Tunnel folgen Sie autossh und systemd.

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 macht das Gegenteil: Es öffnet einen Port auf dem Server, der zu Ihrem Rechner zurückführt.

Warum erreichen andere Rechner den Port des Reverse-Tunnels nicht?

Mit dem Standardwert GatewayPorts no lauscht der Server nur auf seinem Loopback. Setzen Sie GatewayPorts clientspecified oder yes in sshd_config und geben Sie den Port in der Firewall frei.

Wie halte ich einen Reverse-SSH-Tunnel dauerhaft offen?

Ein einfaches ssh -R endet, wenn die Verbindung abbricht. Starten Sie es mit autossh und systemd, dann startet es von selbst neu.

Quellen

Mehr zu Tunnel und Jump-Hosts

Alle Anleitungen