Follow-up: Es sieht so aus, als ob die schnelle Reihe von Verbindungsabbrüchen, die mit einigen Monaten der Ausführung jedes Servers zusammenfällt, wahrscheinlich zufällig ist und nur dazu dient, das eigentliche Problem aufzudecken. Der Grund, warum die Verbindung nicht wiederhergestellt werden konnte, liegt mit ziemlicher Sicherheit an den AliveInterval-Werten (kasperds Antwort). Wenn Sie die Option ExitOnForwardFailure verwenden, sollte das Zeitlimit vor dem erneuten Herstellen der Verbindung korrekt angezeigt werden. In den meisten Fällen sollte dies das Problem beheben. Der Vorschlag von MadHatter (das Kill-Skript) ist wahrscheinlich der beste Weg, um sicherzustellen, dass der Tunnel wieder verbunden werden kann, auch wenn alles andere fehlschlägt.
Ich habe einen Server (A) hinter einer Firewall, der an mehreren Ports einen Reverse-Tunnel zu einem kleinen DigitalOcean-VPS (B) initiiert, damit ich über die IP-Adresse von B eine Verbindung zu A herstellen kann. Der Tunnel ist seit ungefähr 3 Monaten durchgehend in Betrieb, ist jedoch in den letzten 24 Stunden plötzlich viermal ausgefallen. Dasselbe geschah vor einiger Zeit bei einem anderen VPS-Anbieter - Monate des einwandfreien Betriebs, 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_B
für jeden Port X), aber wenn es ausgeführt wird, heißt es Warning: remote port forwarding failed for listen port X
.
Wenn Sie /var/log/secure
auf dem Server auf sshd zugreifen, werden die folgenden Fehler angezeigt :
bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X
Das Lösen erfordert einen Neustart des VPS. Bis dahin wird bei allen Versuchen, die Verbindung wiederherzustellen, die Meldung "Remote-Portweiterleitung fehlgeschlagen" angezeigt und funktioniert nicht. Es ist jetzt so weit, dass der Tunnel vor dem Anhalten nur noch etwa 4 Stunden dauert.
Am VPS hat sich nichts geändert, und es handelt sich um einen Einbenutzer-Einzelplatzrechner, der nur als Reverse-Tunnel-Endpunkt dient. Es läuft OpenSSH_5.3p1 unter CentOS 6.5. Es scheint, dass sshd die Ports nicht an seinem Ende schließt, wenn die Verbindung unterbrochen wird. Ich bin nicht in der Lage zu erklären, warum oder warum es nach Monaten eines nahezu perfekten Betriebs plötzlich passieren würde.
Um dies zu verdeutlichen, muss ich zuerst herausfinden, warum sshd es ablehnt, die Ports zu überwachen, nachdem der Tunnel ausfällt. Dies scheint darauf zurückzuführen zu sein, dass sshd die Ports offen lässt und sie niemals schließt. Das scheint das Hauptproblem zu sein. Ich bin mir nur nicht sicher, was dazu führen würde, dass es sich nach Monaten des erwarteten Verhaltens so verhält (dh, die Ports werden sofort geschlossen und das Skript kann erneut verbunden werden).
quelle
Antworten:
Ich stimme MadHatter zu, dass es wahrscheinlich Portweiterleitungen von unterbrochenen SSH-Verbindungen sind. Auch wenn sich herausstellt, dass Ihr aktuelles Problem etwas anderes ist, können Sie davon ausgehen, dass Sie früher oder später auf solche unterbrochenen SSH-Verbindungen stoßen.
Es gibt drei Möglichkeiten, wie solche unterbrochenen Verbindungen auftreten können:
Es ist nicht sehr wichtig, herauszufinden, welche der drei oben genannten Vorgänge stattfinden, da es eine Methode gibt, die alle drei anspricht. Das ist die Verwendung von Keepalive-Nachrichten.
Sie sollten nach dem
ClientAliveInterval
Schlüsselwort fürsshd_config
und demServerAliveInterval
Intervall fürssh_config
oder suchen~/.ssh/config
.Das Ausführen des
ssh
Befehls in einer Schleife kann problemlos funktionieren. Es ist eine gute Idee, einen Schlafmodus in die Schleife einzufügen, damit Sie den Server nicht überfluten, wenn die Verbindung aus irgendeinem Grund fehlschlägt.Wenn der Client erneut eine Verbindung herstellt, bevor die Verbindung auf dem Server beendet wurde, kann dies dazu führen, dass die neue SSH-Verbindung aktiv ist, aber keine Portweiterleitungen aufweist. Um dies zu vermeiden, müssen Sie das
ExitOnForwardFailure
Schlüsselwort auf der Clientseite verwenden.quelle
-o ExitOnForwardFailure yes
genau das war, was ich brauchte. Das ist eine Sache weniger, die ich herausfinden muss. Zum Nachdenken wollte ich ein Python-Skript schreiben, um diese Warnmeldungen zu analysieren. Das ist viel einfacher. : DExitOnForwardFailure
mir leid, dass ich das beim Schreiben meiner Antwort vergessen habe. Ich habe es jetzt zur Antwort hinzugefügt.-o ExitOnForwardFailure=yes
(beachte das Gleichheitszeichen). Also, wenn jemand darauf stößt, kopiere es nicht und füge es nicht aus meinem vorherigen Kommentar ein, es wird nicht funktionieren. : PSie können den Prozess finden, der den Port auf diesem Server bindet
Es scheint sehr wahrscheinlich, dass es sich um die halbe Funktionsunfähigkeit handelt
sshd
, aber warum Annahmen treffen, wenn Sie Daten haben können? Es ist auch eine gute Möglichkeit für ein Skript, eine PID zu finden, an die das Signal 9 gesendet werden kann, bevor versucht wird, den Tunnel wieder hochzufahren.quelle
Wenn ein
ssh
Tunnel getrennt wird, dauert es eine Weile, bis die Verbindung zurückgesetzt wird, sodass derssh
Prozess weiterhin blockiert wird und ich keine aktiven Tunnel mehr habe und nicht weiß, warum. Eine Umgehungslösung besteht darin, neue Verbindungenssh
in den Hintergrund zu stellen-f
und zu erzeugen, ohne darauf zu warten, dass alte Verbindungen zurückgesetzt werden. Mit dem-o ExitOnForwardFailure=yes
kann die Anzahl neuer Prozesse begrenzt werden. Das-o ServerAliveInterval=60
verbessert die Zuverlässigkeit Ihrer aktuellen Verbindung.Sie können den
ssh
Befehl häufig wiederholencron
, z. B. in einer oder in einer Schleife in Ihrem Skript. Im Folgenden führen wir denssh
Befehl alle 3 Minuten aus:quelle
-o ExitOnForwardFailure=yes
war das, wonach ich gesucht habe, vielen Dank!Meiner Erfahrung nach hat ssh die etwas lästige Angewohnheit, nicht sauber zu beenden, wenn auf dem Remote-System noch etwas läuft. ZB im Hintergrund gestartet. Sie können dies reproduzieren durch:
Ihr ssh wird sich abmelden, aber die Sitzung nicht tatsächlich schließen - bis der Remote-Prozess beendet ist (was nicht der Fall ist, da es sich um eine "while true" -Schleife handelt). Es kann sein, dass etwas Ähnliches passiert - Ihre Sitzung hat einen 'festgefahrenen' Prozess, der von ssh erzeugt wird. Der Port wird weiterhin verwendet und kann daher von Ihrem lokalen Prozess nicht wiederverwendet werden.
quelle
ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &
ausgeführt wird, bewirkt, dass von SSH nichts außer dem Tunnel selbst ausgeführt wird, insbesondere aufgrund der Option -N. Was immer offen gehalten wird, wird auf dem Remote-Server B unter Verwendung von sshd selbst ausgeführt.