SSH-Tunnel verwalten: Portweiterleitungen speichern, starten und stoppen

Speichern Sie jeden Tunnel als Host-Block in ~/.ssh/config mit LocalForward, RemoteForward oder DynamicForward und starten Sie ihn dann über seinen Namen mit ssh -f -N name. Ergänzen Sie den Block um ControlMaster, ControlPath und ControlPersist, dann beenden Sie ihn mit ssh -O exit name, ohne den Prozess zu suchen. ssh -O forward und ssh -O cancel fügen eine Weiterleitung hinzu oder entfernen sie, während der Tunnel weiterläuft.

Sie möchten Tunnel nicht in einer Konfigurationsdatei pflegen und mit pkill beenden? Wardterm führt eine Liste gespeicherter Tunnel, die Sie mit einem Klick starten und stoppen. Zeigen

Aktualisiert am . Ausgeführt mit OpenSSH 10.0 auf Debian 13 in Wegwerf-Containern: ein Client, ein Jump-Host und ein Ziel mit einem kleinen HTTP-Server.

Jeden Tunnel in ~/.ssh/config speichern

Wer die Optionen -L und -R jedes Mal neu tippt, verwechselt früher oder später die Ports. Geben Sie stattdessen jedem Tunnel einen Namen, als eigenen Host-Block:

Host db-tunnel
  HostName 203.0.113.10
  User deploy
  LocalForward 127.0.0.1:5432 127.0.0.1:5432
  ExitOnForwardFailure yes

Host dev-share
  HostName 203.0.113.10
  User deploy
  RemoteForward 127.0.0.1:9000 127.0.0.1:3000

Host socks
  HostName 203.0.113.10
  User deploy
  DynamicForward 127.0.0.1:1080

Jede Zeile ist die Konfigurationsform einer Kommandozeilenoption: LocalForward entspricht -L, RemoteForward entspricht -R und DynamicForward entspricht -D. Zuerst kommen Listen-Adresse und Port, dann ein Leerzeichen, dann das Ziel. Wie bei den Optionen löst der Server das Ziel einer lokalen Weiterleitung auf, 127.0.0.1 meint dort also den Server selbst. Wenn Ihnen die drei Arten neu sind, beginnen Sie mit SSH-Tunnel erklärt: local, remote und dynamic.

Verwenden Sie für Tunnel einen eigenen Namen, nicht den Host, mit dem Sie sich täglich anmelden. Sonst versucht jede Anmeldung, dieselben Ports zu öffnen, und die zweite meldet Address already in use.

Einen Tunnel über seinen Namen starten

ssh -f -N db-tunnel

-N führt keinen Befehl auf dem Server aus, die Verbindung trägt also nur die Weiterleitungen. -f schickt ssh nach der Anmeldung in den Hintergrund, eine Abfrage von Passphrase oder Passwort erreicht Sie also trotzdem zuerst. Ihr Datenbank-Tool kann sich jetzt mit 127.0.0.1:5432 verbinden.

Mit ExitOnForwardFailure yes beendet ein bereits belegter Port ssh mit Exit-Code 255, statt eine Verbindung ohne Tunnel stehen zu lassen. So sieht es aus, wenn Sie denselben Tunnel zweimal starten:

bind [127.0.0.1]:5432: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 5432
Could not request local forwarding.

Mehrere gespeicherte Tunnel auf einmal starten:

for t in db-tunnel socks; do ssh -f -N "$t"; done

Einen Tunnel beenden

Ein Tunnel im Hintergrund ist nur ein ssh-Prozess. Ohne weitere Hilfsmittel suchen Sie ihn und beenden ihn:

ps ax | grep '[s]sh -f -N db-tunnel'
pkill -f 'ssh -f -N db-tunnel'

pkill -f trifft jeden Prozess, dessen Befehlszeile diesen Text enthält. In unseren Tests hat es auch das Shell-Skript beendet, das den Tunnel gestartet hatte, weil das Skript dieselben Wörter enthielt. Ein Control-Socket ist sauberer. Ergänzen Sie den Block um drei Zeilen:

Host db-tunnel
  HostName 203.0.113.10
  User deploy
  LocalForward 127.0.0.1:5432 127.0.0.1:5432
  ExitOnForwardFailure yes
  ControlMaster auto
  ControlPath ~/.ssh/cm-%C
  ControlPersist yes

Jetzt reagiert der Tunnel auf Befehle mit seinem Namen:

ssh -f -N db-tunnel
ssh -O check db-tunnel
ssh -O exit db-tunnel
Master running (pid=27)
Exit request sent.

Über den Socket können auch andere ssh- und scp-Befehle an db-tunnel dieselbe Verbindung nutzen. Details stehen in SSH-Multiplexing mit ControlMaster.

Weiterleitungen ohne neue Verbindung hinzufügen oder entfernen

Mit einem Control-Socket können Sie einen laufenden Tunnel ändern. Die Verbindung und ihre anderen Weiterleitungen bleiben bestehen:

ssh -O forward -L 127.0.0.1:8081:127.0.0.1:8000 db-tunnel
ssh -O cancel -L 127.0.0.1:8081:127.0.0.1:8000 db-tunnel

cancel braucht genau dieselbe Angabe, mit der Sie die Weiterleitung hinzugefügt haben. Das funktioniert auch für -R und -D. Mit -R 0:... wählt der Server einen freien Port, und ssh -O forward gibt ihn aus.

Einen gespeicherten Tunnel am Laufen halten

Ein mit -f gestarteter Tunnel lebt so lange wie seine SSH-Verbindung. Ruhezustand, ein WLAN-Wechsel oder ein Neustart des Servers beenden ihn. Ergänzen Sie den Block um diese Zeilen, damit ssh eine tote Verbindung nach etwa 45 Sekunden erkennt und sich beendet, statt zu hängen:

  ServerAliveInterval 15
  ServerAliveCountMax 3

Danach muss ihn etwas neu starten: eine Schleife, ein Dienstverwalter oder autossh für einen dauerhaften SSH-Tunnel.

Fehler, die gespeicherte Tunnel kaputt machen

  • Doppelpunkt statt Leerzeichen. LocalForward 5432:127.0.0.1:5432 ist das Format der Kommandozeile, nicht das der Konfiguration. ssh meldet Missing target argument, und in unserem Test hat diese eine falsche Zeile die Verbindung zu allen Hosts der Datei verhindert.
  • Lauschen auf allen Schnittstellen. LocalForward 0.0.0.0:5432 ... oder GatewayPorts yes lassen andere Rechner in Ihrem Netzwerk den Tunnel nutzen. Bleiben Sie bei 127.0.0.1, wenn Sie das nicht ausdrücklich wollen.
  • Zwei Tunnel auf demselben lokalen Port. Nur der erste startet. Geben Sie jedem gespeicherten Tunnel einen eigenen Port.
  • Weiterleitung vom Server abgelehnt. Öffnet sich der Port, scheitern Verbindungen aber mit administratively prohibited, hat der Server AllowTcpForwarding für Sie abgeschaltet.

Fragen

Wie sehe ich, welche SSH-Tunnel laufen?

Führen Sie ps ax | grep '[s]sh -f -N' aus, um ssh-Prozesse im Hintergrund mit ihren Optionen aufzulisten. Bei einem Tunnel mit Control-Socket antwortet ssh -O check name direkt. In einer interaktiven Sitzung drücken Sie Enter und tippen ~#, um die weitergeleiteten Verbindungen zu sehen.

Kann ein Befehl mehrere Tunnel starten?

Ja. Schreiben Sie mehrere LocalForward- oder DynamicForward-Zeilen in einen Host-Block, dann öffnen sich alle mit einem einzigen ssh -f -N name. Ist ein Port belegt und ExitOnForwardFailure aktiv, bleibt keiner offen.

Warum stoppt mein gespeicherter Tunnel nach dem Ruhezustand oder einem Netzwechsel?

Der Tunnel lebt in einer einzigen SSH-Verbindung, und die bricht ab, wenn das Netz weg ist. Setzen Sie ServerAliveInterval, damit ssh das bemerkt, und starten Sie ihn mit einer Schleife oder mit autossh neu.

Quellen

Mehr zu Tunnel und Jump-Hosts

Alle Anleitungen