2009-09-08 13:04:22 +0000 2009-09-08 13:04:22 +0000
244
244

Wie hält man einen SSH-Tunnel zuverlässig offen?

Ich benutze einen SSH-Tunnel von der Arbeit aus, um verschiedene idotische Firewalls zu umgehen (das ist ok für meinen Chef :)). Das Problem ist, dass sich die SSH-Verbindung nach einer Weile normalerweise aufhängt und der Tunnel unterbrochen wird.

Wenn ich den Tunnel wenigstens automatisch überwachen könnte, könnte ich den Tunnel neu starten, wenn er sich aufhängt, aber ich habe noch nicht einmal eine Möglichkeit gefunden, das zu tun.

Bonuspunkte für denjenigen, der mir sagen kann, wie ich verhindern kann, dass meine ssh-Verbindung hängt, natürlich!

Antworten (16)

296
296
296
2009-09-08 13:43:51 +0000

Klingt, als bräuchten Sie autossh . Damit wird ein ssh-Tunnel überwacht und bei Bedarf neu gestartet. Wir verwenden es seit ein paar Jahren und es scheint gut zu funktionieren.

autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C

Mehr Details über den Parameter -M hier

40
40
40
2009-09-28 13:47:26 +0000

Alle Stateful-Firewalls vergessen eine Verbindung, nachdem sie einige Zeit lang kein Paket für diese Verbindung gesehen haben (um zu verhindern, dass die Statustabellen voll mit Verbindungen werden, bei denen beide Enden gestorben sind, ohne die Verbindung zu schließen). Die meisten TCP-Implementierungen senden ein Keepalive-Paket nach einer langen Zeit, ohne von der anderen Seite zu hören (2 Stunden ist ein üblicher Wert). Wenn es jedoch eine Stateful-Firewall gibt, die die Verbindung vergisst, bevor die Keepalive-Pakete gesendet werden können, wird eine langlebige, aber inaktive Verbindung sterben.

Wenn das der Fall ist, besteht die Lösung darin, zu verhindern, dass die Verbindung inaktiv wird. OpenSSH hat eine Option namens ServerAliveInterval , die verwendet werden kann, um zu verhindern, dass die Verbindung zu lange im Leerlauf ist (als Bonus wird es früher erkennen, wenn die Gegenstelle gestorben ist, auch wenn die Verbindung im Leerlauf ist).

24
24
24
2010-05-29 13:45:08 +0000

Auf Ihrem eigenen Mac oder Linux-Rechner konfigurieren Sie Ihre ssh halten den Server ssh alive alle 3 Minuten. Öffnen Sie ein Terminal und gehen Sie zu Ihrer unsichtbaren .ssh in Ihrem Zuhause:

cd ~/.ssh/

dann erstellen Sie eine 1 zeilige Konfigurationsdatei mit:

echo "ServerAliveInterval 180" >> config

Sie sollten auch hinzufügen:

ServerAliveCountMax xxxx (high number)

Die Vorgabe ist 3, so dass ServerAliveInterval 180 nach 9 Minuten (3 des durch ServerAliveInterval festgelegten 3-Minuten-Intervalls) aufhört zu senden.

23
23
23
2009-09-22 14:58:15 +0000

Ich habe das folgende Bash-Skript verwendet, um immer wieder neue ssh-Tunnel zu erzeugen, wenn der vorherige stirbt. Die Verwendung eines Skripts ist praktisch, wenn Sie keine zusätzlichen Pakete installieren wollen oder können oder einen Compiler verwenden.

while true
do
  ssh <ssh_options> [user@]hostname
  sleep 15
done

Beachten Sie, dass dies eine Schlüsseldatei benötigt, um die Verbindung automatisch aufzubauen, aber das ist auch bei autossh der Fall.

21
21
21
2016-07-28 06:10:14 +0000

Systemd ist hierfür ideal geeignet.

Erstellen Sie eine Servicedatei /etc/systemd/system/sshtunnel.service, die Folgendes enthält:

[Unit]
Description=SSH Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=sshtunnel
ExecStart=/bin/ssh -NT -o ServerAliveInterval=60 -L 5900:localhost:5900 user@otherserver

[Install]
WantedBy=multi-user.target

(Ändern Sie den ssh-Befehl entsprechend)

  • dies wird als Benutzer sshtunnel ausgeführt, stellen Sie also sicher, dass dieser Benutzer zuerst existiert
  • geben Sie systemctl enable sshtunnel ein, um ihn so einzustellen, dass er beim Booten startet
  • geben Sie systemctl start sshtunnel ein, um ihn sofort zu starten

Update Jan 2018 : Einige Distros (z. z. B. Fedora 27) verwenden möglicherweise SELinux-Richtlinien, um die Verwendung von SSH von systemd init zu verhindern. In diesem Fall muss eine benutzerdefinierte Richtlinie erstellt werden, um die erforderlichen Ausnahmen bereitzustellen.

11
11
11
2013-11-28 01:04:34 +0000

Es sieht für mich so aus, als würden Sie alle ServerAliveCountMax falsch interpretieren. So wie ich die Dokumentation verstehe, ist dies die Anzahl der ServerAlive-Meldungen, die unbeantwortet bleiben können, ohne dass die Verbindung beendet wird. In Fällen, wie wir sie hier besprechen, stellt ein hoher Wert also nur sicher, dass eine hängende Verbindung nicht erkannt und beendet wird!

Das einfache Setzen von ServerAliveInterval sollte ausreichen, um das Problem zu lösen, dass eine Firewall die Verbindung vergisst, und das Belassen von ServerAliveCountMax auf einem niedrigen Wert ermöglicht es dem verursachenden Ende, den Fehler zu bemerken und die Verbindung zu beenden, wenn sie trotzdem scheitert.

Was Sie wollen, ist, 1) dass die Verbindung unter normalen Umständen permanent offen bleibt, 2) dass ein Verbindungsfehler erkannt wird und die Ursprungsseite bei einem Fehler beendet wird, und 3) dass der ssh-Befehl bei jedem Beenden neu ausgegeben wird (wie Sie das machen, ist sehr plattformabhängig, das von Jawa vorgeschlagene “while true”-Skript ist eine Möglichkeit, unter OS X habe ich tatsächlich ein launchd-Element eingerichtet).

9
9
9
2014-03-08 21:30:40 +0000

Verwenden Sie immer die SSH-Option ServerAliveInterval, falls die Tunnelprobleme durch abgelaufene NAT-Sitzungen verursacht werden.

Verwenden Sie immer eine Respawning-Methode für den Fall, dass die Verbindung vollständig unterbrochen wird, Sie haben hier mindestens drei Möglichkeiten:

  • autossh-Programm
  • bash-Skript (while true do ssh ...; sleep 5; done) entfernen Sie nicht den sleep-Befehl, ssh kann schnell fehlschlagen und Sie werden zu viele Prozesse respawnen
  • /etc/inittab, um Zugriff auf eine Box zu haben, die in einem anderen Land geliefert und installiert wurde, hinter NAT, ohne Port-Weiterleitung zur Box, können Sie sie so konfigurieren, dass sie einen ssh-Tunnel zurück zu Ihnen erstellt:

  • upstart script auf Ubuntu, wo /etc/inittab nicht verfügbar ist:

oder verwenden Sie immer beide Methoden.

6
6
6
2013-05-30 13:32:05 +0000

Ich habe dieses Problem folgendermaßen gelöst:

~/.ssh/config

Und fügen Sie

ServerAliveInterval 15
ServerAliveCountMax 4

laut man page für ssh_config hinzu:

ServerAliveCountMax
         Sets the number of server alive messages (see below) which may be
         sent without ssh(1) receiving any messages back from the server.
         If this threshold is reached while server alive messages are
         being sent, ssh will disconnect from the server, terminating the
         session. It is important to note that the use of server alive
         messages is very different from TCPKeepAlive (below). The server
         alive messages are sent through the encrypted channel and there‐
         fore will not be spoofable. The TCP keepalive option enabled by
         TCPKeepAlive is spoofable. The server alive mechanism is valu‐
         able when the client or server depend on knowing when a connec‐
         tion has become inactive.

         The default value is 3. If, for example, ServerAliveInterval
         (see below) is set to 15 and ServerAliveCountMax is left at the
         default, if the server becomes unresponsive, ssh will disconnect
         after approximately 45 seconds. This option applies to protocol
         version 2 only.

 ServerAliveInterval
         Sets a timeout interval in seconds after which if no data has
         been received from the server, ssh(1) will send a message through
         the encrypted channel to request a response from the server. The
         default is 0, indicating that these messages will not be sent to
         the server. This option applies to protocol version 2 only.
4
4
4
2015-06-06 23:41:10 +0000

ExitOnForwardFailure yes ist eine gute Ergänzung zu den anderen Vorschlägen. Wenn es eine Verbindung herstellt, aber die Portweiterleitung nicht einrichten kann, ist es für Sie genauso nutzlos, wie wenn es sich gar nicht verbunden hätte.

1
1
1
2012-03-13 12:11:18 +0000

Ein bisschen ein Hack, aber ich mag es, den Bildschirm zu benutzen, um das zu behalten. Ich habe derzeit einen Remote-Forward, der schon seit Wochen läuft.

Beispiel, lokal starten:

screen
ssh -R ......

Wenn der Remote-Forward angewendet wird und Sie eine Shell auf dem entfernten Computer haben:

screen
Ctrl + a + d

Sie haben jetzt einen ununterbrochenen Remote-Forward. Der Trick besteht darin, screen auf beiden Seiten auszuführen

1
1
1
2015-07-30 14:02:55 +0000

Kürzlich hatte ich selbst dieses Problem, da diese Lösungen erfordern, dass Sie das Passwort jedes Mal neu eingeben müssen, wenn Sie ein Passwort-Login verwenden, habe ich sshpass in einer Schleife zusammen mit einer Texteingabeaufforderung verwendet, um zu vermeiden, dass das Passwort in der Batch-Datei enthalten ist.

Ich dachte, ich teile meine Lösung in diesem Thead, falls jemand anderes das gleiche Problem hat:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh user@address -p port
    sleep 1
done
1
1
1
2009-09-08 14:09:33 +0000

Es gibt zwar Tools wie autossh, die beim Neustart von ssh-Sitzungen helfen… aber was ich wirklich nützlich finde, ist der Befehl “screen”. Es erlaubt Ihnen, Ihre ssh-Sitzungen wieder aufzunehmen, auch wenn Sie die Verbindung getrennt haben. Besonders nützlich, wenn Ihre Verbindung nicht so zuverlässig ist, wie sie sein sollte.

…vergessen Sie nicht zu markieren, dass dies die ‘richtige’ Antwort ist, wenn es Ihnen hilft k! ;-)

1
1
1
2009-09-08 13:17:28 +0000

Ich hatte das Bedürfnis, einen SSH-Tunnel langfristig zu warten. Meine Lösung lief von einem Linux-Server aus, und es ist nur ein kleines C-Programm, das ssh mit schlüsselbasierter Authentifizierung neu aufruft.

Ich bin mir nicht sicher, was das Hängen angeht, aber ich hatte schon Tunnel, die aufgrund von Timeouts gestorben sind.

Ich würde gerne den Code für den Respawner zur Verfügung stellen, aber ich kann ihn im Moment nicht finden.

0
0
0
2017-07-15 00:04:11 +0000

Da autossh nicht unseren Anforderungen entspricht (es existiert mit Fehler, wenn es sich nicht beim ersten Versuch mit dem Server verbinden kann), haben wir eine reine Bash-Anwendung geschrieben: https://github.com/aktos-io/link-with-server

Sie erstellt standardmäßig einen Reverse-Tunnel für den sshd-Port (22) des NODE auf dem Server. Wenn Sie andere Aktionen durchführen müssen (wie das Weiterleiten zusätzlicher Ports, das Senden von Mails bei der Verbindung usw.), können Sie die Skripte on-connect und on-disconnect in den Ordner legen.

0
0
0
2009-09-28 10:27:21 +0000

Ich habe ähnliche Probleme mit meinem vorherigen ISP gehabt. Bei mir war es bei jeder tcp-Verbindung, beim Besuch von Websites oder beim Senden von Mails dasselbe.

Die Lösung war, eine VPN-Verbindung über UDP zu konfigurieren (ich verwendete OpenVPN). Diese Verbindung war toleranter gegenüber dem, was die Verbindungsabbrüche verursachte. Dann kann man jeden Dienst über diese Verbindung laufen lassen.

Es kann immer noch Probleme mit der Verbindung geben, aber da der Tunnel toleranter ist, wird jede ssh-Sitzung eher eine kurze Verzögerung spüren, als dass die Verbindung unterbrochen wird.

Hierfür benötigen Sie einen VPN-Dienst, den Sie auf Ihrem eigenen Server einrichten können.

0
0
0
2020-02-20 15:09:46 +0000

Sie können ganz einfach den Befehl tmux auf Ihrem Remote-Server verwenden. Er ermöglicht es Ihnen, eine “Sitzung” auf dem entfernten Rechner zu öffnen, in der Sie Ihren entfernten Code ausführen werden.

Dann können Sie den entfernten Rechner unbesorgt verlassen (oder in Ihrem Fall die Verbindung verlieren), da Ihr Code sicher in Ihrer tmux-Sitzung läuft.

Wenn Sie sich schließlich wieder mit dem entfernten Server verbinden, müssen Sie nur tmux attach eingeben, um zu der Sitzung zurückzukehren, die Sie zuvor geöffnet hatten, und das war’s.