Frage Wie kann man einen SSH-Tunnel zuverlässig offen halten?


Ich benutze einen SSH-Tunnel von der Arbeit um verschiedene idotische Firewalls zu umgehen (es ist in Ordnung mit meinem Chef :)). Das Problem ist, dass nach einer Weile die SSH-Verbindung normalerweise hängt und der Tunnel kaputt ist.

Wenn ich den Tunnel zumindest automatisch überwachen könnte, könnte ich den Tunnel neu starten, wenn er hängt, aber ich habe noch nicht einmal einen Weg gefunden, das zu tun.

Bonuspunkte für denjenigen, der mir sagen kann, wie ich meine ssh-Verbindung daran hindern kann, aufzuhängen, natürlich!


200
2017-09-08 13:04


Ursprung


Es ist dein Tunnel tot weil Inaktivität? Ich hatte dieses Problem, wenn ich Häfen von meinem Telefon tunnelte, also beendete ich schließlich, Dummybefehle auf der Verbindung zu erzeugen, um sie "lebendig" zu machen, die watch Befehl wie: watch -n1 60 echo "wiiiii". Der Tunnel wird nicht sterben, wenn das Netzwerk nicht kaputt ist oder Sie es nicht benutzen. - erm3nda
Verbunden: unix.stackexchange.com/q/200239 - sampablokuper


Antworten:


Klingt wie du brauchst autossh. Dies wird einen SSH-Tunnel überwachen und bei Bedarf neu starten. Wir haben es seit ein paar Jahren benutzt und es scheint gut zu funktionieren.

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

Weitere Details zum Parameter -M Hier


239
2017-09-08 13:43



+1 für autosh, es tut, was es auf der Dose sagt. Ich glaube, ein Teil seiner Funktionalität besteht auch darin, Keep-Alive-Style-Pakete zu senden, um jegliche Art von Timeout zu verhindern. - akent
Könnten Sie den Beispieltunnel benutzen? autossh in der Antwort? - Ehtesh Choudhury
autossh -f -nNT -i ~/keypair.pem -R 2000:localhost:22 username@myoutsidebox.com   Sie werden bemerken, dass ich dies mit -nNT eingerichtet habe, das kein entferntes Terminal erstellt, sodass ich autosh in den Hintergrund setzen kann, und die Option -i für SSH, eine .pem-Datei zu verwenden. Wenn Sie die Verbindung immer offen halten, empfehle ich Ihnen, das zusätzliche Setup zu verwenden. - juckele
Für das, was es wert ist, sieht es in der Regel besser aus, das wegzulassen -M Parameter: bugs.debian.org/cgi-bin/bugreport.cgi?bug=351162 - rinogo
Wenn es nicht funktioniert und Sie Schlüssel verwenden, überprüfen Sie diese Antwort - serverfault.com/a/545093/288788 - muttonUp


Alle statusbehafteten Firewalls vergessen eine Verbindung, nachdem sie ein Paket für eine bestimmte Zeit nicht gesehen haben (um zu verhindern, dass die Statustabellen mit Verbindungen überfüllt werden, bei denen beide Enden abstarben, 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 jedoch eine statusbehaftete Firewall vorhanden ist, die die Verbindung vergisst, bevor die Keepalive-Pakete gesendet werden können, wird eine langlebige, aber inaktive Verbindung absterben.

Wenn dies der Fall ist, besteht die Lösung darin, zu verhindern, dass die Verbindung inaktiv wird. OpenSSH hat eine Option namens ServerAliveInterval mit dem verhindert werden kann, dass die Verbindung zu lange ungenutzt bleibt (als Bonus wird erkannt, wenn der Peer früher gestorben ist, selbst wenn die Verbindung inaktiv ist).


34
2017-09-28 13:47



Das angegebene Intervall ist in Sekunden angegeben, sodass Sie eine Feinabstimmung vornehmen können. Wenn Ihre statusbehaftete Firewall eine Leerlaufzeit von 5 Minuten hat, reichen 60 oder 120 Sekunden aus, um die Verbindung offen zu halten. Es ist eine der Möglichkeiten, wie ich meine SSH-Sitzungen durch meinen Home-Router offen halte. - Darren Hall
Danke, das hat geholfen. Aber beachten Sie (von einer niedriger eingestuften Antwort hier, superuser.com/a/146641/115515) Wenn Sie ServerAliveInterval und nicht ServerAliveCountMax angeben, können Sie ssh absichtlich früher als gewünscht trennen. - metamatt
@metamatt, diese Antwort mit niedrigerem Rang, auf die Sie verweisen, ist aus gutem Grund niedriger eingestuft: IT IS WRONG. - Lambart


Auf Ihrem eigenen Mac oder Linux-Rechner konfigurieren Sie Ihre SSH halten Sie den Server SSH alle 3 Minuten am Leben. Öffne ein Terminal und nimm deine unsichtbare .ssh bei dir zu Hause:

cd ~/.ssh/ 

Erstellen Sie dann eine 1-zeilige Konfigurationsdatei mit:

echo "ServerAliveInterval 180" >> config

Sie sollten auch hinzufügen:

ServerAliveCountMax xxxx (high number)

Der Standardwert ist 3, sodass ServerAliveInterval 180 nach 9 Minuten (3 des von ServerAliveInterval angegebenen 3-Minuten-Intervalls) nicht mehr sendet.


22
2018-05-29 13:45



Beachten Sie, dass Ihr Befehl nicht empfohlen wird, wenn Sie bereits eine Konfigurationsdatei haben. Die Verwendung von >> zur Weiterleitung wäre viel besser! - Peltier
warum tut ServerAliveInterval 180 gib uns 6 Minuten? Intuition lässt mich das versuchen: 180/60 == 3. Also, tut es ServerAliveInterval in Vielfachen von 30 Sekunden arbeiten? - nemesisfixx
@mcnemesis: ServerAliveInterval 180 bedeutet 3 Minuten. ServerAliveCountMax Standard von 3 bedeutet 3 dieser Intervalle, also 9 Minuten. - metamatt
Ich stimme diese Antwort ab, weil ich danke, dass Sie ServerAliveCountMax erwähnt haben, und was passiert, wenn Sie ServerAliveInterval ohne ServerAliveCountMax angeben. Aber wie in den vorhergehenden Kommentaren bemerke ich, dass die Berechnung auf "wird aufhören zu senden" falsch ist, und ich denke, diese Antwort würde besser funktionieren, wenn sie nur die Informationen zu diesen Optionen liefert und uns nicht sagt, wie man sie mit cd- und echo-Befehlen anwendet . - metamatt
Downvoting, weil es keinen Sinn macht, ServerAliveCountMax auf eine "hohe Zahl" zu setzen. ServerAliveCountMax gibt an, wie oft versucht wird, die "Keepalive" -Nachricht zu senden, bevor er aufgibt. Der Standardwert ist 3, dh mit ServerAliveInterval 180 wird NUR dann gesendet, wenn der Server nach 9 Minuten nicht reagiert hat. In diesem Fall ist Ihre Verbindung wahrscheinlich wirklich tot. - Lambart


Ich habe das folgende Bash-Skript benutzt, um immer neue SSH-Tunnel zu erzeugen, wenn der vorherige stirbt. Die Verwendung eines Skripts ist praktisch, wenn Sie keine zusätzlichen Pakete installieren oder installieren oder den Compiler verwenden möchten.

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

Beachten Sie, dass hierfür eine Schlüsseldatei erforderlich ist, um die Verbindung automatisch herzustellen. Dies ist jedoch auch bei autosh der Fall.


20
2017-09-22 14:58



Sie sollten irgendwelche Gründe hinzufügen, dass Sie dieses Skript über autosh verwenden würden, oder ist es nur so einfacher? - kyrias
Das würde nicht helfen, wenn ssh selbst einfriert, oder? - nafg
Es hilft, wenn Sie Dinge auf dem Server nicht installieren können. autossh kommt nicht vorinstalliert und Bürokratie ist manchmal sehr stumpf. - quarkex
Ja, vorzuziehen, Dinge nicht installieren zu müssen. Ich mache es seit einem Jahr auf diese Weise, da ich nur auf diese Weise einen Remote-Rechner erreichbar halten kann (sogar crontab so einstellen, dass es beim Neustart ausgeführt wird). Es ist nie gescheitert, und noch wichtiger, ich weiß, warum es niemals scheitern wird. - sudo


Mir scheint, dass Sie ServerAliveCountMax falsch interpretieren. Wie ich die Docs verstehe, ist es die Anzahl der Server Alive-Nachrichten, die unbeantwortet bleiben können, ohne dass die Verbindung beendet wird. In Fällen, wie wir sie hier behandeln, wird die Einstellung auf einen hohen Wert nur sicherstellen, dass eine unterbrochene 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. Wenn ServerAliveCountMax niedrig bleibt, erkennt das Ursprungsende den Fehler und beendet es, wenn die Verbindung trotzdem fehlschlägt.

Was Sie wollen ist, 1) dass die Verbindung unter normalen Umständen dauerhaft offen bleibt, 2) dass ein Verbindungsfehler erkannt wird und die ursprüngliche Seite bei einem Fehler beendet wird und 3) dass der ssh Befehl jedes Mal neu ausgegeben wird exits (wie du das tust ist das sehr plattformabhängig, das von Jawa vorgeschlagene "while true" -Skript ist eine Möglichkeit, auf OS XI tatsächlich ein launchd-Item einzurichten).


9
2017-11-28 01:04





Verwenden Sie immer ServerAliveInterval SSH-Option für den Fall, dass die Tunnelprobleme durch abgelaufene NAT-Sitzungen generiert werden.

Verwenden Sie immer eine Respawn-Methode, wenn die Verbindung vollständig abgebaut wird. Sie haben hier mindestens drei Möglichkeiten:

  • autosh Programm
  • Bash-Skript (while true do ssh ...; sleep 5; done) nicht den Schlafbefehl entfernen, ssh kann schnell scheitern und Sie werden zu viele Prozesse respawnen
  • /etc/inittabUm Zugriff auf eine Box zu haben, die in einem anderen Land ausgeliefert und installiert wurde, hinter NAT, ohne Portweiterleitung an die Box, können Sie sie so konfigurieren, dass ein ssh-Tunnel zu Ihnen zurückfindet:

    tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
    
  • Upstart-Skript auf Ubuntu, wo /etc/inittab ist nicht verfügbar:

    start on net-device-up IFACE=eth0
    stop on runlevel [01S6]
    respawn
    respawn limit 180 900
    exec ssh -i /path/to/rsaKey -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip
    post-stop script
        sleep 5
    end script
    

oder verwende immer beide Methoden.


9
2018-03-08 21:30



+1 für Inline-Option, falls Sie nicht für alle Ihre SSH-Verbindungen wollen - user1146334
Sie schreiben "für den Fall, dass die Verbindung vollständig abgebaut wird". Jetzt verstehe ich nicht, welche Probleme sich autossh selbst beheben, und was nicht? Ich dachte natürlich, es würde sich um irgendeine unterbrochene Verbindung kümmern, wie zum Beispiel das Kabel für ein paar Stunden herausziehen, aber vielleicht nicht? - Mads Skjern


Systemd ist dafür bestens geeignet.

Erstellen Sie eine Servicedatei /etc/systemd/system/sshtunnel.service 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 Befehl ssh entsprechend)

  • Dies wird als Benutzer ausgeführt sshtunnel Stellen Sie also sicher, dass der Benutzer zuerst existiert
  • Problem systemctl enable sshtunnel um es beim Booten zu starten
  • Problem systemctl start sshtunnel um sofort zu beginnen

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


8
2017-07-28 06:10



Das sieht meinem Kern sehr ähnlich: gist.github.com/guettli/... Feedback ist willkommen! - guettli
Ausgezeichnet für einen systemd System. Wenn man benutzt Restart=on-failure Das manuelle Beenden des SSH-Clients führt nicht zu einem Neustart von Systemd als SSH-Client mit erfolgreichem Beenden. - David Tonhofer
Wenn Sie ssh von einem als Argument übergebenen (bash) Skript starten wollen ExecStart zum Beispiel um das zu bauen ssh argument list, mache einfache checks etc und rufe es dann wie im Skript auf exec /bin/ssh -N .... Hier ist mein Befehl: exec /bin/ssh -N -oExitOnForwardFailure=Yes -oTCPKeepAlive=no -oServerAliveInterval=5 -oServerAliveCountMax=6 -i "${LOCAL_PRIVATE_KEY}" -L "${TUNNEL_INLET}:${TUNNEL_OUTLET}" "${REMOTE_USER}@${REMOTE_MACHINE}" woher TUNNEL_INLET="127.0.0.1:3307" und TUNNEL_OUTLET="127.0.0.1:3306" - David Tonhofer


Ich habe dieses Problem damit gelöst:

Bearbeiten

~/.ssh/config

Und füge hinzu

ServerAliveInterval 15
ServerAliveCountMax 4

Gemäß Man Seite für ssh_config:

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.

6
2018-05-30 13:32



Alle 15 Sekunden scheint es ziemlich oft zu pingen auf dem Server. - Lambart
@Lambart aber wenn die Verbindung wirklich flockig ist und Verbindungen oft abbricht, erkennt es zumindest eine tote Verbindung und gibt die Möglichkeit, es früher zu versuchen. - binki


ExitOnForwardFailure yes ist eine gute Ergänzung zu den anderen Vorschlägen. Wenn es verbindet, aber die Portweiterleitung nicht herstellen kann, ist es für Sie genauso nutzlos, als wenn es überhaupt nicht verbunden wäre.


3
2018-06-06 23:41



Dies ist eine sehr gute Idee. Sogar autosh ist nutzlos, wenn die vorherige Verbindung auf der entfernten Seite früher als auf dem lokalen Host als abgelaufen wahrgenommen wird, da in diesem Fall der lokale Host versuchen wird, sich erneut zu verbinden, aber die Weiterleitung kann nicht hergestellt werden, da der Port noch offen ist. - Raúl Salinas-Monteagudo


Ich hatte ein Bedürfnis, einen SSH-Tunnel langfristig aufrechtzuerhalten. Meine Lösung lief von einem Linux-Server, und es ist nur ein kleines C-Programm, das ssh mit der schlüsselbasierten Authentifizierung neu erstellt.

Ich bin mir nicht sicher über das Hängen, aber ich hatte Tunnel aufgrund von Timeouts sterben.

Ich würde gerne den Code für den Respawner zur Verfügung stellen, aber ich kann es jetzt anscheinend nicht finden.


1
2017-09-08 13:17





während es Tools wie autossh gibt, die helfen, die ssh-Sitzung neu zu starten ... was ich als wirklich nützlich empfinde, ist das Ausführen des Befehls 'screen'. Es erlaubt Ihnen, Ihre ssh-Sitzungen fortzusetzen, selbst nachdem Sie die Verbindung getrennt haben. Besonders nützlich, wenn Ihre Verbindung nicht so zuverlässig ist, wie es sein sollte.

... vergiss nicht, dies zu markieren ist die 'richtige' Antwort, wenn es dir hilft k! ;-)


1
2017-09-08 14:09



... aber die Frage war, wie man SSH-Tunnel offen hält, nicht nur eine Terminal-Sitzung. Der Bildschirm ist großartig! - akent
Ich benutze bereits Bildschirm, aber es löst mein Problem nicht: - / Danke für Ihre Antwort. - Peltier