SSH-Tunnel dauerhaft offen halten mit autossh und systemd

Betreiben Sie den Tunnel als systemd-Dienst mit Restart=always und nehmen Sie autossh -M 0 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes als Befehl. Die Keepalive-Optionen lassen ssh eine tote Verbindung bemerken, autossh startet es neu, und systemd startet alles nach einem Absturz oder Neustart wieder. Verwenden Sie einen eigenen Schlüssel auf einem Konto, das nur genau diesen Tunnel öffnen kann.

Brauchen Sie den Tunnel nur während der Arbeit, nicht als Dienst? Wardterm hält ihn auf Ihrem Gerät bereit, ganz ohne Unit-Datei. Zeigen

Aktualisiert am . autossh 1.4g, systemd 257 und OpenSSH 10.0 unter Debian 13 in privilegierten Wegwerf-Containern.

1. Einen Schlüssel für den Tunnel erzeugen

Legen Sie auf dem Rechner, der den Tunnel startet, ein lokales Konto und einen Schlüssel ohne Passphrase an, weil der Dienst unbeaufsichtigt startet. Speichern Sie dann den Host-Schlüssel des Servers, damit die erste Verbindung nicht zum Nachfragen anhält:

sudo apt install autossh
sudo useradd -m -s /usr/sbin/nologin tunnel
sudo -u tunnel mkdir -m 700 /home/tunnel/.ssh
sudo -u tunnel ssh-keygen -t ed25519 -N "" -C tunnel -f /home/tunnel/.ssh/id_ed25519
ssh-keyscan -t ed25519 server | sudo -u tunnel tee /home/tunnel/.ssh/known_hosts

Vergleichen Sie diesen Host-Schlüssel mit dem echten Fingerabdruck des Servers, bevor Sie sich darauf verlassen. Siehe known_hosts erklärt.

2. Das Konto auf dem Server einschränken

Ein Schlüssel ohne Passphrase auf einem entfernten Rechner sollte nur diesen Tunnel öffnen. Legen Sie auf dem Server ein Konto namens tunnel an und tragen Sie den öffentlichen Schlüssel in dessen ~/.ssh/authorized_keys ein:

restrict,port-forwarding ssh-ed25519 AAAA... tunnel

Fügen Sie dann Folgendes am Ende von /etc/ssh/sshd_config hinzu:

Match User tunnel
  AllowTcpForwarding remote
  PermitListen localhost:2222
  X11Forwarding no
  ForceCommand /usr/sbin/nologin
sudo sshd -t && sudo systemctl reload ssh

Das Ergebnis haben wir mit diesem Schlüssel getestet:

VersuchErgebnis
-R 2222:localhost:22Funktioniert
-R 2223:localhost:22remote port forwarding failed for listen port 2223
Einen Befehl oder eine Shell ausführenThis account is currently not available.
-L 9000:localhost:22Verbindung geschlossen, nichts kommt durch

Die letzte Zeile braucht den Match-Block. Mit nur permitlisten="localhost:2222" in der authorized_keys funktionierte in unserem Test eine -L-Weiterleitung weiterhin, sodass der Schlüssel Dienste auf dem Loopback des Servers erreichen konnte. Mehr zu Schlüsseloptionen steht unter SSH-Schlüssel einschränken.

3. Den Dienst anlegen

Speichern Sie dies als /etc/systemd/system/autossh-tunnel.service:

[Unit]
Description=Reverse SSH tunnel to server
Wants=network-online.target
After=network-online.target

[Service]
User=tunnel
Environment=AUTOSSH_GATETIME=0
ExecStart=/usr/bin/autossh -M 0 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -i /home/tunnel/.ssh/id_ed25519 -R 2222:localhost:22 tunnel@server
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now autossh-tunnel.service
systemctl status autossh-tunnel

Was die einzelnen Teile tun

  • -M 0 schaltet den eigenen Monitor-Port von autossh aus, sodass es ssh nur dann neu startet, wenn ssh sich beendet. Die autossh-README schlägt die Keepalive-Optionen als Ersatz für den Monitor-Port vor.
  • ServerAliveInterval=30 und ServerAliveCountMax=3 lassen ssh sich nach etwa 90 bis 120 Sekunden Stille vom Server beenden. In unserem Test dauerte es bei 5 Sekunden Intervall mit gleicher Anzahl 20 Sekunden, und ein 100 Sekunden langes Einfrieren mit diesen Werten löste es nicht aus.
  • ExitOnForwardFailure=yes lässt ssh sich beenden, wenn der Port nicht geöffnet werden kann. Ohne die Option können Sie eine lebende Verbindung ohne Tunnel bekommen.
  • AUTOSSH_GATETIME=0 lässt autossh weiter versuchen, auch wenn der erste Versuch scheitert, was beim Booten wichtig ist.
  • Restart=always bringt den Dienst zurück, wenn autossh selbst stirbt.
  • Verwenden Sie hier nicht das -f von autossh, denn systemd erwartet, dass der Prozess im Vordergrund bleibt.

4. Die Wiederherstellung beobachten

Was wir tatenWas geschah
Sitzung auf dem Server beendetautossh startete sofort ein neues ssh
Server 28 Sekunden eingefroren, bei 5 Sekunden IntervallTimeout, server server not responding. nach 20 Sekunden, dann eine neue Verbindung, sobald der Server zurück war
autossh mit kill -9 beendet, und sein sshsystemd startete den Dienst neu, und NRestarts stieg auf 1

Das können Sie selbst mit journalctl -u autossh-tunnel -f beobachten. Auf dem Server zeigt ss -ltn | grep 2222 den Port.

Wenn der Port nach einem Netzwerkausfall belegt bleibt

Nach einem echten Ausfall kann der Server die alte Verbindung und ihren Port noch halten, sodass die neue mit remote port forwarding failed scheitert, bis die alte ein Timeout erreicht. Fügen Sie im Match-Block auf dem Server hinzu:

  ClientAliveInterval 30
  ClientAliveCountMax 3

Der Server trennt dann tote Clients nach etwa 90 Sekunden, und die Wiederholungen gelingen.

Weitere Gründe für einen belegten Port finden Sie unter SSH-Tunnel: Address already in use und remote port forwarding failed.

Brauchen Sie autossh überhaupt

Mit systemd und den Keepalive-Optionen funktioniert auch einfaches ssh. ssh beendet sich, und Restart=always startet es neu. Ersetzen Sie den Befehl in der Unit durch:

ExecStart=/usr/bin/ssh -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -i /home/tunnel/.ssh/id_ed25519 -R 2222:localhost:22 tunnel@server

In unserem Test erholte sich das von einer beendeten Sitzung mit einem systemd-Neustart, nach den 10 Sekunden von RestartSec. autossh startet früher neu und ist die Option, wenn Sie kein systemd haben.

Ein Unterschied fiel uns auf: systemctl restart protokollierte status=1/FAILURE für autossh beim Beenden. Der Dienst startete danach trotzdem normal wieder.

Fragen

Was bewirkt autossh -M 0?

Es schaltet den Überwachungsport ab. autossh startet ssh dann nur neu, wenn ssh sich beendet, und ServerAliveInterval und ServerAliveCountMax sorgen dafür, dass das bei einer toten Verbindung passiert.

Brauche ich autossh, wenn ich systemd nutze?

Nicht unbedingt. Auch ein normales ssh mit den Keepalive-Optionen und Restart=always kommt zurück. autossh startet schneller neu und läuft auch ohne systemd.

Warum scheitert mein Reverse-Tunnel nach einem Netzausfall?

Der Server hält eventuell noch die alte Verbindung und ihren Port. Setzen Sie auf dem Server ClientAliveInterval 30 und ClientAliveCountMax 3, dann trennt er tote Clients nach etwa 90 Sekunden.

Quellen

Mehr zu Tunnel und Jump-Hosts

Alle Anleitungen