Wie kann ein "fallengelassener" aber noch angeschlossener Reverse-SSH-Tunnel wieder aufgenommen werden?

402
BlandCorporation

Ich habe einen Remote-Raspberry-Pi-Computer, der sich hinter seiner restriktiven Firewall über einen umgekehrten SSH-Tunnel mit meinem Server verbindet. Stellen Sie sich vor, dieser Raspberry Pi befindet sich auf einem schwer zugänglichen Dach eines Gebäudes in einem anderen Land (vielleicht während eines Sturms). Ich möchte, dass seine Verbindung zuverlässig ist.

Um eine Verbindung zum Server herzustellen, führt das Raspberry Pi einen Prozess wie folgt aus:

while true; do ssh -R 19999:localhost:22 www.sern.pro sleep 30 done 

Der Teil 19999:localhost:22bedeutet im Wesentlichen, dass der gesamte Datenverkehr an Port 19999 auf dem Server an Port 22 des Raspberry Pi weitergeleitet werden muss. Ich kann also eine Verbindung zum Raspberry Pi herstellen, indem ich den Server mit SSHing verbindet und dann einen Befehl wie den folgenden ausführt:

ssh localhost -p 19999 

Dies funktioniert normalerweise einwandfrei und auf dem Server netstat --all --timers --program --numeric | egrep '127.0.0.1:*(LISTEN|.*)' | sortlistet ein Befehl wie die umgekehrte SSH-Verbindung etwa wie folgt auf:

tcp 0 0 127.0.0.1:19999 0.0.0.0:* LISTEN 2972/5 off (0.00/0/0) 

Gelegentlich habe ich jedoch festgestellt, dass diese Auflistung auf dem Server verschwindet, während der Raspberry Pi seine SSH-Verbindung zum Server aufrechterhält . Das heißt, der Befehl ssh localhost -p 19999führt zu einer Fehlermeldung wie der folgenden:

ssh: connect to host localhost port 19999: Connection refused 

Die Raspberry Pi SSH-Verbindung bleibt jedoch einwandfrei und kann Befehle auf dem Server ausführen. Ich weiß nicht die richtigen Worte, um zu beschreiben, was in diesem Fall schief geht.

Also ... ohne einen Flug buchen und auf das Dach eines Gebäudes klettern zu können, wie könnte ich diese aktive SSH-Verbindung als richtigen SSH-Tunnel wieder herstellen? Wie kann ich wieder auf den lokalen Port zugreifen?

0

2 Antworten auf die Frage

1
Oleg Bolden

Vor mehr als einem Jahrzehnt autosshwurde für solche Zwecke ein Utility geschrieben.

Sie können das folgende Verbindungsskript verwenden

#!/bin/sh export AUTOSSH_GATETIME=0   autossh -M 0 -o "PubkeyAuthentication=yes" \ -o "StrictHostKeyChecking=false" \ -o "PasswordAuthentication=no" \ -o "ExitOnForwardFailure=yes" \ -o "ServerAliveInterval 60" \ -o "ServerAliveCountMax 3" \ -fNR 19999:localhost:22 www.sern.pro 

Natürlich müssen Sie vor dem Starten dieses Skripts eine schlüsselbasierte Authentifizierung einrichten.

0
Genaro Morales

Das Problem, das Sie sehen, bedeutet, dass die Verbindung nicht verfügbar ist. Wenn Sie am Ende des Befehls alle Verbindungen auflisten, sehen Sie möglicherweise, dass die Verbindung für diesen Port nicht mehr unter LISTEN steht und jetzt TIME-WAIT oder ist CLOSE-WAIT, das bedeutet, dass die Verbindungen noch "lebendig" sind, jedoch nur als ein laufender Prozess in der Himbeere.

Damit dies funktioniert, können Sie ein Skript erstellen, das prüft, ob eine reversessh-Verbindung besteht, wenn es nicht eingerichtet ist.

Um das Problem zu lösen, können Sie dem Skript Code hinzufügen, um zu überprüfen, ob sich in der Einheit eine ssh-Prozess-ID befindet. Wenn Sie eine Markierungsdatei haben, beenden Sie diesen Prozess, um den Tunnel erneut zu starten.

Beispiel: Sie haben eine leere Datei namens RESTARTSSH. In Ihrem Skript können Sie überprüfen, ob diese Datei vorhanden ist. Wenn ja, suchen Sie nach der Prozess-ID der SSH, und beenden Sie sie, und starten Sie den Tunnel erneut.

Zur Überprüfung der Prozess-ID können Sie Folgendes verwenden:

ps -ef | grep ServerAliveInterval | grep -v grep | awk ''