SSH-Remote-Portweiterleitung fehlgeschlagen

SSH-Remote-Portweiterleitung fehlgeschlagen

Nachverfolgen:Es sieht so aus, als ob die schnelle Serie von Verbindungsabbrüchen, die mit ein paar Monaten Betrieb jedes Servers zusammenfällt, wahrscheinlich zufällig ist und nur dazu dient, das eigentliche Problem aufzudecken. Der Grund, warum die erneute Verbindung fehlgeschlagen ist, liegt mit ziemlicher Sicherheit an den AliveInterval-Werten (Antwort von kasperd). Die Verwendung der Option ExitOnForwardFailure sollte dafür sorgen, dass das Timeout vor der erneuten Verbindung ordnungsgemäß abläuft, was das Problem in den meisten Fällen lösen sollte. Der Vorschlag von MadHatter (das Kill-Skript) ist wahrscheinlich der beste Weg, um sicherzustellen, dass der Tunnel erneut verbunden werden kann, auch wenn alles andere fehlschlägt.

Ich habe einen Server (A) hinter einer Firewall, der auf mehreren Ports einen Reverse-Tunnel zu einem kleinen DigitalOcean VPS (B) initiiert, sodass ich mich über die IP-Adresse von B mit A verbinden kann. Der Tunnel funktioniert seit etwa 3 Monaten zuverlässig, ist aber in den letzten 24 Stunden plötzlich viermal ausgefallen. Dasselbe passierte vor einiger Zeit bei einem anderen VPS-Anbieter – Monatelang einwandfreier Betrieb, dann plötzlich mehrere schnelle Ausfälle.

Ich habe ein Skript auf Maschine A, das den Tunnelbefehl automatisch ausführt ( ssh -R *:X:localhost:X address_of_Bfür jeden Port X), aber bei der Ausführung erscheint die Meldung Warning: remote port forwarding failed for listen port X.

Beim Aufrufen des SSHD /var/log/secureauf dem Server werden diese Fehler angezeigt:

bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X

Zur Lösung des Problems ist ein Neustart des VPS erforderlich. Bis dahin führen alle Versuche, die Verbindung wiederherzustellen, zur Meldung „Remote-Portweiterleitung fehlgeschlagen“ und funktionieren nicht. Es ist jetzt so weit gekommen, dass der Tunnel nur noch etwa 4 Stunden hält, bevor er abbricht.

Am VPS hat sich nichts geändert und es handelt sich um eine Maschine zur einmaligen Verwendung und für einen einzelnen Benutzer, die nur als Reverse-Tunnel-Endpunkt dient. Sie läuft mit OpenSSH_5.3p1 unter CentOS 6.5. Es scheint, dass sshd die Ports an seinem Ende nicht schließt, wenn die Verbindung verloren geht. Ich kann mir nicht erklären, warum das so ist oder warum das jetzt plötzlich passiert, nach Monaten nahezu perfekten Betriebs.

Zur Klarstellung muss ich zunächst herausfinden, warum sshd sich weigert, auf den Ports zu lauschen, nachdem der Tunnel fehlgeschlagen ist. Dies scheint daran zu liegen, dass sshd die Ports offen lässt und sie nie schließt. Das scheint das Hauptproblem zu sein. Ich bin mir nur nicht sicher, was dazu führen könnte, dass es sich so verhält, nachdem es sich monatelang so verhalten hat, wie ich es erwarte (d. h. die Ports sofort schließt und dem Skript erlaubt, die Verbindung wiederherzustellen).

Antwort1

Ich stimme mit MadHatter überein, dass es sich wahrscheinlich um Portweiterleitungen von nicht mehr funktionierenden SSH-Verbindungen handelt. Selbst wenn sich Ihr aktuelles Problem als etwas anderes herausstellt, können Sie davon ausgehen, dass Sie früher oder später auf solche nicht mehr funktionierenden SSH-Verbindungen stoßen werden.

Es gibt drei Möglichkeiten, wie solche unterbrochenen Verbindungen entstehen können:

  • Einer der beiden Endpunkte wurde neu gestartet, während das andere Ende der Verbindung völlig inaktiv war.
  • Einer der beiden Endpunkte hat die Verbindung geschlossen, aber zum Zeitpunkt der Schließung war die Verbindung vorübergehend unterbrochen. Der Ausfall dauerte nach der Schließung der Verbindung noch einige Minuten, sodass das andere Ende nie von der geschlossenen Verbindung erfuhr.
  • Die Verbindung ist an beiden Endpunkten der SSH-Verbindung noch voll funktionsfähig, aber jemand hat irgendwo zwischen ihnen ein Stateful-Gerät platziert, das die Verbindung aufgrund von Inaktivität abgebrochen hat. Dieses Stateful-Gerät wäre entweder ein NAT oder eine Firewall. Die von Ihnen bereits erwähnte Firewall ist ein Hauptverdächtiger.

Herauszufinden, welches der drei oben genannten Probleme eintritt, ist nicht besonders wichtig, da es eine Methode gibt, die alle drei Probleme löst. Und zwar die Verwendung von Keepalive-Nachrichten.

ClientAliveIntervalSie sollten sich das Schlüsselwort für sshd_configund das ServerAliveIntervalIntervall für ssh_configoder ansehen ~/.ssh/config.

Das Ausführen des sshBefehls in einer Schleife kann problemlos funktionieren. Es ist eine gute Idee, auch einen Sleep-Befehl in die Schleife einzufügen, damit der Server nicht überlastet wird, wenn die Verbindung aus irgendeinem Grund fehlschlägt.

Wenn der Client die Verbindung wiederherstellt, bevor die Verbindung auf dem Server beendet wurde, kann es passieren, dass die neue SSH-Verbindung aktiv ist, aber keine Portweiterleitungen hat. Um dies zu vermeiden, müssen Sie das ExitOnForwardFailureSchlüsselwort auf der Clientseite verwenden.

Antwort2

Wenn ein Tunnel getrennt wird, dauert es bei mir ssheine Weile, bis die Verbindung wiederhergestellt wird. Der sshProzess wird also weiterhin blockiert und ich habe keine aktiven Tunnel, und ich weiß nicht, warum. Eine Problemumgehungslösung besteht darin, es sshin den Hintergrund zu stellen -fund neue Verbindungen zu erstellen, ohne darauf zu warten, dass alte Verbindungen wiederhergestellt werden. Damit -o ExitOnForwardFailure=yeslässt sich die Anzahl neuer Prozesse begrenzen. Dadurch -o ServerAliveInterval=60wird die Zuverlässigkeit Ihrer aktuellen Verbindung verbessert.

Sie können den sshBefehl häufig wiederholen, beispielsweise in einer cronoder in einer Schleife in Ihrem Skript. Im Folgenden führen wir den sshBefehl beispielsweise alle 3 Minuten aus:

while (1)
do
    ssh -f user@hostname -Rport:host:hostport -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=60
    sleep 180
done

Antwort3

Den Prozess, der den Port auf diesem Server bindet, finden Sie mit

sudo netstat -apn|grep -w X

Es scheint sehr wahrscheinlich, dass es sich um das halb nicht mehr funktionierende handelt sshd, aber warum Annahmen treffen, wenn man Daten haben kann? Es ist auch eine gute Möglichkeit für ein Skript, eine PID zu finden, an die Signal 9 gesendet werden kann, bevor versucht wird, den Tunnel wieder aufzubauen.

Antwort4

Meiner Erfahrung nach hat SSH die etwas lästige Angewohnheit, nicht sauber beendet zu werden, wenn auf dem Remote-System noch „etwas“ läuft. Beispielsweise wenn es im Hintergrund gestartet wurde. Sie können dies folgendermaßen reproduzieren:

ssh <server>
while true; do  sleep 60; done&
exit

Ihr SSH meldet sich ab, schließt die Sitzung aber nicht wirklich – bis der Remote-Prozess beendet wird (was nicht der Fall ist, da es sich um eine „while true“-Schleife handelt). Möglicherweise passiert etwas Ähnliches – Ihre Sitzung hat einen „feststeckenden“ Prozess, der von SSH gestartet wird. Der Port bleibt in Verwendung und kann daher von Ihrem lokalen Prozess nicht wiederverwendet werden.

verwandte Informationen