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:... |
|---|---|---|
no | Nur Loopback | Nur Loopback, die Adresse wird ignoriert |
clientspecified | Nur Loopback | Alle Adressen, von anderen Rechnern erreichbar |
yes | Alle Adressen | Alle 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 nound nutzen Sie-Jwie 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.