Bildschirm oder ähnliches zum automatischen Wiederherstellen einer flockigen SSH-Verbindung

18

In einer unzuverlässigen WLAN-Umgebung muss ich oft über ssh eine Verbindung zu einem Server herstellen. Auf dem Server führe ich den Bildschirm aus. Wenn die Verbindung getrennt wird, kann ich die Bildschirmsitzung wieder herstellen und fortsetzen und dort weitermachen, wo ich aufgehört habe. Der Verbindungsverlust ist jedoch immer noch eine große Zeitsenke: Wenn die Verbindung unterbrochen wird, während ich abbrich bin auf dem Server, neigt das Terminalfenster zum Einfrieren. Ich muss diese Registerkarte beenden, eine neue öffnen, ssh erneut auf den Server übertragen und die Bildschirmsitzung fortsetzen. Ich habe dies mit dem Ausführen von Bildschirm auf dem Server und Bildschirm lokal versucht. In beiden Fällen kann es zum Einfrieren kommen, wenn die Verbindung unterbrochen wird.

Gibt es eine Möglichkeit, wie ich es mit dem Bildschirm oder dem Bildschirm selbst tun kann, bei der automatisch versucht wird, die Verbindung wiederherzustellen und die Sitzung aufrechtzuerhalten, sodass ich die Verbindung nicht manuell wiederherstellen muss? Oft, wenn ich die Verbindung verliere, denke ich, dass es nur für eine sehr kurze Zeit ist - vielleicht weniger als eine Sekunde.

Ich benutze Ubuntu 14.04 LTS, MATE Edition. Vielen Dank

Max Williams
quelle
4
Bezüglich "das Shell-Fenster friert ein": Das liegt daran, dass Ihr lokaler SSH nicht weiß, dass die Verbindung unterbrochen ist. Drücken Sie <Enter>und geben Sie ein ~., um Ihre Seite anzuweisen, die Verbindung zu trennen, und wiederholen Sie einfach den letzten ssh-Befehl, um die Verbindung wiederherzustellen (z. B. mit dem Aufwärtspfeil oder !!).
Alexis
@alexis das klingt nach einer schnelleren Möglichkeit, die Verbindung wiederherzustellen, danke! Ich würde es lieben, wenn es automatisch passiert ...
Max Williams

Antworten:

23

Sie können sich Folgendes ansehen mosh: https://mosh.org/

Sie können einen Jump-Server mit einer zuverlässigen Internetverbindung einrichten, mit dem Sie mosheine Verbindung herstellen, und dann sshSitzungen mit jedem von Ihnen verwalteten Server durchführen. Der Grund, warum ich die Verwendung eines Jump-Servers vorschlage, ist, dass Sie möglicherweise nicht moshauf den von Ihnen verwalteten Servern installieren möchten .

Ein weiterer Vorteil von moshist, dass es auf UDP anstatt auf TCP basiert und Ihre Sitzung eine Änderung der IP-Adresse überstehen kann, zum Beispiel von WiFi zu einer mobilen Internetverbindung.

Nur um es klar zu machen, moshist dies kein Ersatz screen, sondern vielmehr ssh. Es ist immer noch eine gute Idee, sie zu verwenden screen, da sie moshselbst keine Möglichkeit bietet, die Verbindung zu Ihrer Sitzung wiederherzustellen, wenn der Client aus irgendeinem Grund stirbt.

rostiges shackleford
quelle
Danke, es ist nur der eine Server (meistens) und wir besitzen ihn, also sollte ich Mosh installieren können. Ich werde das überprüfen.
Max Williams
Eigentlich stellt sich heraus, dass unsere Installation zu schwierig ist, weil unser Server ziemlich alt ist (oder ich sollte sagen, dass wir ein altes Ubuntu verwenden). :(
Max Williams
@MaxWilliams wie alt ist es? Sogar LTS 12.4 wird nicht mehr unterstützt. Und warum nicht einfach versuchen, es selbst zu kompilieren
phuclv
Während ich die mosh-Dokumente lese, benötigen Sie mosh-server auf jedem Host, den Sie remote verwalten möchten. Trotzdem auf jeden Fall interessant.
Wildcard
1
Für mich ist der Anschluss an ein tmux-Terminal über mosh die stabilste Lösung.
Nemo
3

Ich benutze es tmuxseit einigen Jahren und meiner Erfahrung nach stellt es die Verbindung automatisch wieder her. Zumindest dann, wenn die Verbindung nur für relativ kurze Zeit ausfällt. Beachten Sie, dass ich eigentlich byobumit tmux als Backend verwende. Ich weiß nicht , ob diese Robustheit ein Merkmal ist tmuxoder byobuoder sogar von der Kombination der beiden, aber ich schlage vor , Sie geben sowohl einen Versuch.

Ich verbinde mich von meiner lokalen Arch-Installation über ein VPN mit verschiedenen entfernten Ubuntu-Servern. Ich habe es gerade getestet, indem ich mein Netzwerkkabel abgezogen habe, während ich mit der Fernbedienung verbunden war. Die Sitzung wurde unterbrochen, aber sobald mein Kabel wieder eingesteckt war, wurde sie nahtlos fortgesetzt.

Als ich meinen Router durch einen Neustart testete, kehrte die Verbindung jedoch nicht zurück. Ich nehme an, es hat etwas damit zu tun, wie lange das Netzwerk ausgefallen ist, aber es scheint sich wieder zu verbinden, wenn es nur ein paar Sekunden ausgefallen ist.

Wenn es relevant ist, mache ich das alles mit terminatormeinem Terminal-Emulator.

Alle drei sind in den Ubuntu-Repositories verfügbar:

sudo apt-get install tmux terminator byobu

Ich bin aber ganz sicher nicht , dass entweder tmuxoder byobubesser bei ssh Abschaltungen Handhabung. Ich weiß nur, dass sie meiner Erfahrung nach häufig von kurzen Verbindungsverlusten herrühren. Das kann aber auch an anderen Aspekten meiner Konfiguration liegen.

terdon
quelle
1
Beim Neustart Ihres Routers wurde Ihnen möglicherweise eine andere öffentliche IP-Adresse zugewiesen, wodurch die tcpVerbindung unterbrochen wurde . Meiner Erfahrung nach sshkann dies bei zeitweiligen Netzwerkausfällen sehr belastbar sein. Ich glaube nicht, dass dies mit der Tatsache zu tun hat, dass Sie tmuxinnerhalb des sshFensters arbeiten.
Rusty Shackleford
3
Ich wollte dasselbe sagen: Selbst mit normalem SSH können Sie eine kurze Unterbrechung bewältigen, solange die TCP-Verbindung nicht abbricht. Dies könnte der Fall sein, wenn Ihre Schnittstelle heruntergefahren wird oder ein übereifriger Router sie abbricht (NAT-Router könnten den NAT-Status beim Neustart vergessen und vorhandene Verbindungen trennen), oder ClientAlive/ ServerAlivelöst aus, oder ... Ich habe jedoch keine Ahnung, was byobupassiert .
Ilkkachu
Ja, aber das OP scheint bei Verbindungsfehlern einzufrieren, während ich dies nicht tue. Aber ja, du hast recht, ich sehe das auch mit einfachem ssh und ohne tmux. Trotzdem, vielleicht kann der Bildschirm nicht damit umgehen?
Terdon
2
@MaxWilliams tmuxist im Grunde eine modernere Alternative zu screen, ja. Als ich anfing, so zu arbeiten, wie ich es jetzt tat und so etwas brauchte, schlug meine flüchtige Lektüre vor, dass tmuxdies heutzutage die bessere Wahl ist. Ich bin mir auch nicht hundertprozentig sicher, dass es eine bessere Verwaltung verlorener Verbindungen bietet. Ich weiß nur, dass es sich von kurzen Ausfällen erholt, die ich erlebt habe. Ob das an tmuxetwas anderem liegt, weiß ich nicht. Aber es scheint einen Versuch wert :). Byobu ist im Grunde ein Frontend für screen / tmux, kein GUI-Terminal-Emulator. Es ist jedoch äußerst nützlich: byobu.org
terdon
2
tmux unternimmt nichts gegen Verbindungsunterbrechungen. Es funktioniert mit dem von ssh bereitgestellten Endgerät. Mit der ssh-Verbindung steht und fällt alles.
Jonas Schäfer
2

Verwenden Sie die ServerAliveOptionen von ssh, um festzustellen, wann die Verbindung fehlgeschlagen ist.

ServerAliveCountMax
Legt die Anzahl der Server-Alive-Nachrichten fest (siehe unten), die gesendet werden dürfen, ohne dass ssh (1) Nachrichten vom Server zurückerhält. Wenn dieser Schwellenwert erreicht wird, während Server Alive-Nachrichten gesendet werden, trennt ssh die Verbindung zum Server und beendet die Sitzung. Es ist wichtig zu beachten, dass sich die Verwendung von Server Alive-Nachrichten stark von TCPKeepAlive (siehe unten) unterscheidet. Die Server-Alive-Nachrichten werden über den verschlüsselten Kanal gesendet und sind daher nicht fälschbar. Die von TCPKeepAlive aktivierte TCP-Keepalive-Option kann gefälscht werden. Der Server-Alive-Mechanismus ist nützlich, wenn der Client oder Server wissen muss, wann eine Verbindung inaktiv geworden ist.

Der Standardwert ist 3. Wenn beispielsweise ServerAliveInterval (siehe unten) auf 15 gesetzt ist und ServerAliveCountMax auf dem Standardwert belassen wird und der Server nicht mehr reagiert, wird die Verbindung nach ca. 45 Sekunden getrennt.

ServerAliveInterval
Legt ein Zeitlimit in Sekunden fest, nach dessen Ablauf ssh (1) eine Nachricht über den verschlüsselten Kanal sendet, um eine Antwort vom Server anzufordern, wenn keine Daten vom Server empfangen wurden. Der Standardwert ist 0, was angibt, dass diese Nachrichten nicht an den Server gesendet werden.

Wenn Sie also ServerAliveInterval5 einstellen , sshwird die Verbindung automatisch getrennt, wenn das Netzwerk für 15 Sekunden unterbrochen wird.

Barmar
quelle
Zu brechen , eine SSH - Sitzung mit Gewalt, I drücken ~.(oder zuerst eingeben, dann ~.) , bestehend aus: Escape - Zeichen ~und dem Befehl , um die Sitzung zu brechen.
IMZ - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Das setzt voraus, dass man merkt, dass die Verbindung hängt. Wenn Sie das Keepalive von SSH verwenden, wird der Fehler automatisch erkannt.
Barmar
Das klingt wirklich nützlich, danke, ich werde es auf jeden Fall versuchen, wenn ich das nächste Mal in der "Flaky Zone" bin.
Max Williams
@Barmar Ja, stimmt. Ich habe auch über das Problem nachgedacht, zu bestimmen, ob die Verbindung wirklich unterbrochen ist, oder ob ich durch Drücken einer Taste versehentlich diese Tasten an die Gegenseite senden kann ... Und ich kenne keine gute Lösung.
imz - Ivan Zakharyaschev
2

Unter ähnlichen Bedingungen verwende ich eshellTRAMP (über ssh) in Emacs. TRAMP sorgt dafür, dass die Verbindung bei Bedarf wiederhergestellt wird, ohne dass ich große Probleme damit habe, die gewünschten Befehle für die Remote-Shell zu geben.

Eshell eignet sich jedoch nicht als Terminal, dh zum Ausführen von Befehlen, die mit dem Terminal etwas Besonderes tun, oder zum kontinuierlichen (inkrementellen) Ausdrucken über einen längeren Zeitraum.

Grundsätzlich ist es ziemlich einfach, mit TRAMP in Emacs damit zu beginnen:

M-x eshell
cd /user@host:
imz - Ivan Zakharyaschev
quelle
1

Haftungsausschluss

Wenn Ihre SSH-Verbindung einen kurzen Netzwerkausfall nicht übersteht, lässt TCP etwas anderes nicht zu ssh.

Siehe unten für Details. Sowieso:

Die schnellste und schmutzigste Lösung ohne Abhängigkeiten

Erstellen Sie ein Shell-Skript wie folgt:

#!/bin/sh -

# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'

# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255

# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
    ssh $timeout_options -t "$@" screen -dR
    status=$?
    # You can add a `sleep` command here or a counter or whatever
    # you might need as far as rate/retry limiting.
done
exit "$status"

Dies führt nur eine dumm-einfache Schleife aus, mit der versucht wird, eine Verbindung sshherzustellen und eine Verbindung herzustellen screen. Übergeben Sie den Host oder was auch immer Sie normalerweise sshals Befehlszeilenargumente an Ihren Aufruf übergeben würden.

Die erneute Verbindung basiert lediglich darauf, ob SSH einen Fehler bei der Verbindung meldet, was bedeutet, dass es keine Intelligenz zum Erkennen von Nicht-SSH-Fehlern wie "Sie haben WiFI buchstäblich nicht aktiviert" oder was auch immer hat, aber das spielt wahrscheinlich keine Rolle Sie

Ich gehe davon aus, dass Sie über ssh-agenteinen SSH-Schlüssel ohne Passphrase verfügen , mit dem eine erneute Verbindung ohne zusätzliche Eingaben von Ihnen hergestellt werden kann.

Es wird eine winzige Racebedingung geben, bei der Sie, wenn Sie ^Cwährend eines erneuten Verbindungsaufbaus genau den richtigen, von Menschen nicht wahrnehmbaren Sekundenbruchteil treffen , das Skript beenden können, anstatt die Verbindung ^Czum Client-Terminal weiterzuleiten Zerdrücke nicht ^Czu eifrig.

Einfachste zusätzliche Softwarelösung

Sie können das Programm autossh ausprobieren , das in Ihrem Ubuntu-Paket-Repository verfügbar sein sollte.

Wenn Sie es aus dem Quellcode erstellen oder prüfen müssen, handelt es sich um ein einzelnes C-Programm, das ohne zusätzliche Bibliotheken als Abhängigkeiten kompiliert wird, mehr Informationen zur Überprüfung der Verbindungsbelebung zu haben scheint als mein Hack oben, und es wird auch mit einem praktischen rscreenSkriptbefehl ausgeliefert, der auto -anhängt an screen.

Einzelheiten

Wie sshnormal erholt

Nur zur Überprüfung, da ich Dinge nicht gerne sage, ohne mich selbst zu überprüfen, habe ich einen kleinen Test durchgeführt, bevor ich antwortete:

Ich habe mit einem Linux-Gerät auf mein WLAN zugegriffen, eine SSH-Verbindung zu einem anderen Gerät in meinem LAN hergestellt, überprüft, ob ich eine funktionierende sshVerbindung zum anderen Ende habe (Befehle ausführen usw.), und dann auf dem Client das WLAN getrennt (wodurch die Schnittstelle verursacht wurde) zu dekonfigurieren: keine IP-Adressen mehr), ein paar weitere Zeichen in die ssh-Sitzung eingegeben (natürlich keine Antwort) und dann erneut mit meinem WLAN verbunden - die erneute Verbindung schlug mindestens einmal aufgrund eines schlechten Signals und anderer Faktoren fehl , dann endlich wieder verbunden: Ich wartete ungefähr fünf Sekunden, sshbis sich die Sitzung erholte, nichts geschah, also drückte ich eine weitere Taste, und die sshSitzung wurde sofort wieder lebendig, wobei alle Tasten, die ich während der Trennung eingegeben hatte, in der Befehlszeile angezeigt wurden.

Sehen Sie, sshschreiben / lesen Sie einfach in den TCP-Netzwerk-Socket, bis das Betriebssystem meldet, dass ein Fehler aufgetreten ist, und TCP ist tatsächlich sehr tolerant gegenüber längeren Verbindungsabbrüchen.

Wenn der TCP-Stack in Linux mit den Standard-Kernel-Einstellungen auf seine eigenen Geräte gestellt ist, toleriert er es, dass die Verbindung viele Minuten lang völlig still ist, bevor er die Verbindung für tot erklärt und einen Fehler meldet ssh- bis es endgültig aufgibt, reden wir im Ballpark von ~ 30 Minuten, oder zumindest mit Sicherheit lang genug, um Verbindungsprobleme von einer Sekunde oder einer Minute Dauer zu überstehen.

Im Hintergrund versucht der Linux-TCP-Stack nach und nach, Nachrichten mit immer längeren Verzögerungen erneut abzurufen. Dies bedeutet jedoch, dass Sie möglicherweise eine zusätzliche Verzögerung feststellen, bevor Ihre sshSitzung wieder "lebendig" zu werden scheint.

Warum das manchmal kaputt geht

Häufig wird die Verbindung nach einer erheblich kürzeren Inaktivitätsdauer als der vom TCP-Stack tolerierten Zeitspanne aktiv geschlossen, und der Verbindungsstatus wird dann nicht an Ihren sshClient gemeldet .

Mögliche Kandidaten sind:

  1. Firewalls oder NAT'ing-Router, die Speicher benötigen, um sich an jede Live-TCP-Verbindung zu erinnern - als Optimierung und als Abwehrmaßnahme gegen DOS-Angriffe vergessen sie manchmal einfach Ihre Verbindung und ignorieren dann automatisch die darauf folgenden Pakete, da Pakete in der mitten in einer Verbindung, wenn Sie sich nicht erinnern, dass die bestehende Verbindung ungültig ist.

  2. Besser funktionierende Firewalls / Router injizieren ein TCP-RST-Paket, das normalerweise als connection reset by peerFehlermeldung angezeigt wird. Das zurückgesetzte Paket ist jedoch ein "Fire-and-Forget" -Paket. Wenn also in diesem Moment die Verbindung zu Ihrem Client weiterhin Probleme aufweist, wird das TCP-RST-Paket gelöscht Paket auch zurücksetzen, Ihr Client wird denken, dass die Verbindung noch besteht.

  3. Der Server selbst verfügt möglicherweise über eine Firewall-Richtlinie, mit der unerwartete Pakete stillschweigend verworfen werden. Dadurch werden die Verbindungswiederaufnahmeversuche des Clients abgebrochen, wenn der Server denkt, dass die Verbindung geschlossen ist, der Client jedoch nicht: Ihr Client versucht weiterhin, die Verbindung fortzusetzen, der Server jedoch Ignorieren, da es keine Live-Verbindung gibt, zu der diese Pakete im Firewall-Status des Servers gehören.

    Da Sie Linux verwenden, prüfen Sie sorgfältig, ob Ihr Server iptables/ ip6tables(oder nftob Sie das neue Material verwenden) genau das zulässt, was Sie zulassen, oder nicht. Es ist üblich, neue / eingerichtete / verwandte Pakete auf dem TCP-SSH-Port zuzulassen , aber keine "ungültigen". Wenn Sie im Hintergrund alles ablegen, was nicht zulässig ist, kann dieses übliche Setup nach kurzen Verbindungsproblemen zu solchen Einfrierungen führen .

  4. Ihr SSH-Server selbst ist möglicherweise so konfiguriert, dass die Verbindung nach einer gewissen Zeit der Inaktivität geschlossen wird, indem Sie eine der OpenSSH-Optionen für Keepalive-Pakete für TCP- oder SSH-Clients verwenden. An sich führt dies nicht zu unbestimmten Hängen, aber es kann Sie in einen der oben beschriebenen Zustände versetzen.

  5. Es ist möglich, dass Sie ihm nicht genug Zeit geben, um sich von selbst zu lösen, nachdem Sie in den Zustand gekommen sind, in dem Ihre sshSitzung aufgelegt hat.

mtraceur
quelle