it-swarm.com.de

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

Ich benutze einen SSH-Tunnel von der Arbeit, um verschiedene idotische Firewalls zu umgehen (bei meinem Chef ist das in Ordnung :)). Das Problem ist, dass nach einer Weile die SSH-Verbindung normalerweise unterbrochen wird und der Tunnel unterbrochen wird.

Wenn ich den Tunnel zumindest automatisch überwachen könnte, könnte ich den Tunnel neu starten, wenn er hängt, aber ich habe nicht einmal eine Möglichkeit gefunden, dies zu tun.

Bonuspunkte für denjenigen, der mir sagen kann, wie ich verhindern kann, dass meine SSH-Verbindung hängt!

223
Peltier

Klingt wie Sie brauchen autossh . Dadurch wird ein SSH-Tunnel überwacht und bei Bedarf neu gestartet. Wir haben es für ein paar Jahre benutzt und es scheint gut zu funktionieren.

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

Weitere Details zum -M-Parameter hier

267
KeithB

Alle Stateful Firewalls vergessen eine Verbindung, nachdem sie einige Zeit kein Paket für diese Verbindung gesehen haben (um zu verhindern, dass die Statustabellen mit Verbindungen voll werden, bei denen beide Enden gestorben sind, ohne die Verbindung zu schließen). Die meisten TCP Implementierungen senden nach einer langen Zeit ein Keepalive-Paket, ohne von der anderen Seite zu hören (2 Stunden sind ein üblicher Wert). Wenn es jedoch eine Stateful Firewall gibt, die die Verbindung vergisst, bevor die Keepalive-Pakete gesendet werden können, wird eine langlebige, aber inaktive Verbindung unterbrochen.

In diesem Fall besteht die Lösung darin, zu verhindern, dass die Verbindung inaktiv wird. OpenSSH verfügt über die Option ServerAliveInterval , mit der verhindert werden kann, dass die Verbindung zu lange inaktiv ist (als Bonus wird erkannt, wenn der Peer früher gestorben ist, auch wenn die Verbindung inaktiv ist).

37
CesarB

Konfigurieren Sie Ihren ssh auf Ihrem eigenen Mac oder Linux-Computer und halten Sie den ssh-Server alle 3 Minuten am Leben. Öffne ein Terminal und bring deine unsichtbare .ssh zu dir nach Hause:

cd ~/.ssh/ 

dann erstelle 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 den Sendevorgang nach 9 Minuten beendet (3 des von ServerAliveInterval angegebenen 3-Minuten-Intervalls).

23
David Shaw

Ich habe das folgende Bash-Skript verwendet, um weiterhin neue ssh-Tunnel zu erzeugen, wenn der vorherige stirbt. Die Verwendung eines Skripts ist praktisch, wenn Sie keine zusätzlichen Pakete installieren oder den Compiler verwenden können.

while true
do
  ssh <ssh_options> [[email protected]]hostname
  sleep 15
done

Beachten Sie, dass dies eine Schlüsseldatei erfordert, um die Verbindung automatisch herzustellen. Dies ist jedoch auch bei autossh der Fall.

21
Jawa

Dafür ist Systemd bestens geeignet.

Erstellen Sie eine Servicedatei /etc/systemd/system/sshtunnel.service mit:

[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 [email protected]

[Install]
WantedBy=multi-user.target

(Ändern Sie den Befehl ssh entsprechend.)

  • dies wird als Benutzer sshtunnel ausgeführt. Stellen Sie daher sicher, dass der Benutzer zuerst vorhanden ist
  • geben Sie systemctl enable sshtunnel ein, um festzulegen, dass es beim Booten gestartet wird
  • gib systemctl start sshtunnel ein, um sofort zu starten

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

13
IanB

Mir scheint, dass Sie ServerAliveCountMax falsch interpretieren. Nach meinem Verständnis ist es die Anzahl der Server-Alive-Nachrichten, die unbeantwortet bleiben können, ohne dass die Verbindung beendet wird. Wenn Sie also in den hier beschriebenen Fällen einen hohen Wert festlegen, wird nur sichergestellt, dass eine unterbrochene Verbindung nicht erkannt und beendet wird!

Das einfache Einstellen von ServerAliveInterval sollte ausreichen, um das Problem zu lösen, dass eine Firewall die Verbindung vergisst. Wenn Sie ServerAliveCountMax niedrig lassen, kann das ursprüngliche Ende den Fehler feststellen und die Verbindung beenden, wenn die Verbindung trotzdem fehlschlägt.

Was Sie möchten, ist, 1) dass die Verbindung unter normalen Umständen permanent geöffnet bleibt, 2) dass ein Verbindungsfehler erkannt wird und die Ursprungsseite bei einem Fehler beendet wird, und 3) dass der Befehl ssh jedes Mal neu ausgegeben wird Exits (wie Sie das machen, ist sehr plattformabhängig, das von Jawa vorgeschlagene "while true" -Skript ist eine Möglichkeit, unter OS XI tatsächlich ein launchd-Element einzurichten).

9
user2793784

Verwenden Sie immer die SSH-Option ServerAliveInterval, wenn die Tunnelprobleme durch abgelaufene NAT Sitzungen generiert werden.

Verwenden Sie immer eine Respawn-Methode, wenn die Konnektivität vollständig ausfällt. Hier haben Sie mindestens drei Möglichkeiten:

  • autossh-Programm
  • bash-Skript (while true do ssh ...; sleep 5; done) entfernt den Befehl sleep nicht, ssh schlägt möglicherweise schnell fehl und Sie werden zu viele Prozesse erneut erzeugen
  • /etc/inittab, um Zugriff auf eine Box zu haben, die in einem anderen Land hinter NAT geliefert und installiert wurde, ohne dass ein Port an die Box weitergeleitet wird, können Sie diese so konfigurieren, dass ein SSH-Tunnel zu Ihnen zurückgeht:

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

    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 [email protected]
    post-stop script
        sleep 5
    end script
    

oder immer beide Methoden anwenden.

9
claudiuf

Ich habe dieses Problem folgendermaßen gelöst:

Bearbeiten

~/.ssh/config

Und füge hinzu

ServerAliveInterval 15
ServerAliveCountMax 4

Laut man page 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
nachopro

ExitOnForwardFailure yes ist eine gute Ergänzung zu den anderen Vorschlägen. Wenn eine Verbindung hergestellt wird, die Portweiterleitung jedoch nicht hergestellt werden kann, ist dies für Sie genauso nutzlos, als ob überhaupt keine Verbindung hergestellt worden wäre.

3
jcomeau_ictx

Ein bisschen hacken, aber ich benutze gerne Bildschirm, um dies zu halten. Ich habe derzeit eine Remote-Weiterleitung, die seit Wochen ausgeführt wird.

Beispiel, lokal starten:

screen
ssh -R ......

Wenn die Remote-Weiterleitung angewendet wird und Sie eine Shell auf dem Remote-Computer haben:

screen
Ctrl + a + d

Sie haben jetzt eine ununterbrochene Remote-Weiterleitung. Der Trick besteht darin, den Bildschirm an beiden Enden auszuführen

1
landypro

Vor kurzem hatte ich dieses Problem, da Sie bei diesen Lösungen jedes Mal das Kennwort erneut eingeben müssen, wenn Sie eine Kennwortanmeldung verwenden. Ich habe sshpass in einer Schleife zusammen mit einer Textaufforderung verwendet, um zu vermeiden, dass das Kennwort in der Batchdatei enthalten ist.

Dachte, ich würde meine Lösung auf diesem Thead teilen, falls jemand das gleiche Problem hat:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh [email protected] -p port
    sleep 1
done
1
Brainfloat

Ich musste einen SSH-Tunnel langfristig warten. Meine Lösung wurde von einem Linux-Server ausgeführt und es ist nur ein kleines C-Programm, das ssh mithilfe der schlüsselbasierten Authentifizierung wiederherstellt.

Ich bin mir nicht sicher, ob ich hängen soll, aber ich habe Tunnel wegen Timeouts sterben lassen.

Ich würde gerne den Code für den Respawner bereitstellen, aber ich kann ihn augenblicklich nicht finden.

1
baumgart

während es tools wie autossh gibt, die helfen, ssh session neu zu starten ... was ich wirklich nützlich finde, ist, den 'screen'-befehl auszuführen. Es ermöglicht Ihnen, Ihre SSH-Sitzungen auch nach dem Trennen der Verbindung fortzusetzen. Besonders nützlich, wenn Ihre Verbindung nicht so zuverlässig ist, wie sie sein sollte.

... vergessen Sie nicht zu markieren, dies ist die "richtige" Antwort, wenn es Ihnen hilft, k! ;-)

1
koss

Da autossh nicht unseren Anforderungen entspricht (es ist fehlerhaft, wenn es beim ersten Versuch keine Verbindung zum Server herstellen kann), haben wir eine reine Bash-Anwendung geschrieben: https://github.com/aktos-io/link-with-server

Standardmäßig wird ein umgekehrter Tunnel für den sshd-Port (22) des NODE auf dem Server erstellt. Wenn Sie weitere Aktionen ausführen müssen (z. B. Weiterleiten zusätzlicher Ports, Senden von E-Mails bei Verbindung usw.), können Sie die Ordner on-connect und on-disconnect für Ihre Skripte platzieren.

0
ceremcem

Ich hatte ähnliche Probleme mit meinem vorherigen ISP. Für mich war es mit jeder TCP-Verbindung, dem Besuch von Websites oder dem Versenden von E-Mails dasselbe.

Die Lösung bestand darin, eine VPN-Verbindung über UDP zu konfigurieren (ich verwendete OpenVPN). Diese Verbindung war toleranter gegenüber den Ursachen der Unterbrechungen. Dann können Sie jeden Dienst über diese Verbindung ausführen.

Es kann immer noch Probleme mit der Verbindung geben, aber da der Tunnel toleranter ist, fühlt sich jede SSH-Sitzung eher kurz gehalten als getrennt.

Dazu benötigen Sie einen VPN-Dienst online, den Sie auf Ihrem eigenen Server einrichten können.

0
hultqvist