2009-09-08 13:04:22 +0000 2009-09-08 13:04:22 +0000
244
244

Jak niezawodnie utrzymywać otwarty tunel SSH?

Używam tunelu SSH z pracy do obchodzenia różnych idotycznych firewalli (szef mi na to pozwala :)). Problem w tym, że po pewnym czasie połączenie ssh zazwyczaj się zawiesza, a tunel zostaje przerwany.

Gdybym mógł przynajmniej monitorować tunel automatycznie, mógłbym go zrestartować, gdy się zawiesi, ale nie mam nawet pomysłu jak to zrobić.

Punkty bonusowe dla tego, kto powie mi jak zapobiec zawieszaniu się połączenia ssh, oczywiście!

Odpowiedzi (16)

296
296
296
2009-09-08 13:43:51 +0000

Wygląda na to, że potrzebujesz autossh . Będzie to monitorować tunel ssh i restartować go w razie potrzeby. Używamy go od kilku lat i wydaje się, że działa dobrze.

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

Więcej szczegółów na temat parametru -M tutaj

40
40
40
2009-09-28 13:47:26 +0000

Wszystkie stateful firewalle zapominają o połączeniu po tym, jak nie zobaczą pakietu dla tego połączenia przez jakiś czas (aby zapobiec zapełnieniu tablic stanów połączeniami, w których oba końce umarły bez zamknięcia połączenia). Większość implementacji TCP wyśle pakiet keepalive po długim czasie bez odpowiedzi z drugiej strony (2 godziny to często spotykana wartość). Jeśli jednak istnieje stateful firewall, który zapomina o połączeniu zanim pakiety keepalive mogą zostać wysłane, długo żyjące, ale bezczynne połączenie umrze.

W takim przypadku, rozwiązaniem jest zapobieganie bezczynności połączenia. OpenSSH posiada opcję o nazwie ServerAliveInterval która może być użyta do zapobiegania zbyt długiej bezczynności połączenia (jako bonus, wykryje ona, że peer umarł wcześniej, nawet jeśli połączenie jest bezczynne).

24
24
24
2010-05-29 13:45:08 +0000

Na własnej maszynie mac lub linux skonfigurować ssh utrzymać serwer ssh żywy co 3 minuty. Otwórz terminal i przejdź do swojego niewidocznego .ssh w swoim domu:

cd ~/.ssh/

następnie stwórz 1 liniowy plik konfiguracyjny z:

echo "ServerAliveInterval 180" >> config

powinieneś również dodać:

ServerAliveCountMax xxxx (high number)

domyślnie jest 3 więc ServerAliveInterval 180 przestanie wysyłać po 9 minutach (3 z 3-minutowego interwału określonego przez ServerAliveInterval).

23
23
23
2009-09-22 14:58:15 +0000

Używam następującego skryptu Bash do tworzenia nowych tuneli ssh, gdy poprzedni umrze. Użycie skryptu jest przydatne, gdy nie chcesz lub nie możesz zainstalować dodatkowych pakietów lub użyć kompilatora.

while true
do
  ssh <ssh_options> [user@]hostname
  sleep 15
done

Zauważ, że wymaga to pliku klucza do automatycznego nawiązania połączenia, ale tak jest również w przypadku autossh.

21
21
21
2016-07-28 06:10:14 +0000

Systemd idealnie się do tego nadaje.

Utwórz plik usługi /etc/systemd/system/sshtunnel.service zawierający:

[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 user@otherserver

[Install]
WantedBy=multi-user.target

(zmodyfikuj polecenie ssh, aby pasowało)

  • będzie to uruchamiane jako użytkownik sshtunnel, więc upewnij się, że użytkownik istnieje jako pierwszy
  • wydaj systemctl enable sshtunnel, aby ustawić go do uruchamiania w czasie rozruchu
  • wydaj systemctl start sshtunnel, aby uruchomić go natychmiast

Update Jan 2018 : niektóre dystrybucje (np. Fedora 27) mogą używać polityki SELinux, aby zapobiec użyciu SSH z systemd init, w którym to przypadku trzeba będzie utworzyć niestandardową politykę, aby zapewnić niezbędne wyjątki.

11
11
11
2013-11-28 01:04:34 +0000

Wygląda mi na to, że wszyscy źle interpretujecie ServerAliveCountMax. Jak rozumiem w dokumentach, jest to liczba wiadomości server alive, które mogą pozostać bez odpowiedzi bez zerwania połączenia. Więc w przypadkach takich jak omawiamy tutaj, ustawienie go na wysoką wartość zapewni tylko, że zawieszone połączenie nie zostanie wykryte i zakończone!

Po prostu ustawienie ServerAliveInterval powinno wystarczyć do rozwiązania problemu z firewallem zapominającym o połączeniu, a pozostawienie ServerAliveCountMax na niskim poziomie pozwoli na to, aby kończący połączenie zauważył niepowodzenie i zakończył je, jeśli połączenie i tak się nie powiedzie.

To, czego chcesz, to 1) aby połączenie pozostawało otwarte na stałe w normalnych okolicznościach, 2) aby awaria połączenia była wykrywana i aby strona inicjująca kończyła pracę przy niepowodzeniu, oraz 3) aby polecenie ssh było wydawane ponownie za każdym razem, gdy kończy pracę (jak to zrobić, zależy od platformy, skrypt “while true” sugerowany przez Jawa jest jednym ze sposobów, na OS X faktycznie ustawiłem element launchd).

9
9
9
2014-03-08 21:30:40 +0000

Zawsze używaj opcji ServerAliveInterval SSH w przypadku, gdy problemy z tunelem są generowane przez wygasłe sesje NAT.

Zawsze używaj metody respawningu w przypadku całkowitego zaniku łączności, masz tutaj co najmniej trzy opcje:

  • program autossh
  • skrypt basha (while true do ssh ...; sleep 5; done) nie usuwaj komendy sleep, ssh może szybko zawieść i będziesz respawnować zbyt wiele procesów
  • /etc/inittab, aby mieć dostęp do skrzynki dostarczonej i zainstalowanej w innym kraju, za NAT, bez przekierowania portów do skrzynki, możesz skonfigurować ją do tworzenia tunelu ssh z powrotem do Ciebie:

  • skrypt upstartowy na Ubuntu, gdzie /etc/inittab nie jest dostępny:

lub zawsze używać obu metod.

6
6
6
2013-05-30 13:32:05 +0000

Rozwiązałem ten problem w ten sposób:

Edytuj

~/.ssh/config

I dodaj

ServerAliveInterval 15
ServerAliveCountMax 4

Zgodnie z man page dla ssh:

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.
```.
4
4
4
2015-06-06 23:41:10 +0000

ExitOnForwardFailure yes jest dobrym uzupełnieniem innych sugestii. Jeśli łączy się, ale nie może ustanowić przekierowania portu, jest tak samo bezużyteczny dla Ciebie, jak gdyby w ogóle się nie łączył.

1
1
1
2012-03-13 12:11:18 +0000

Trochę hack, ale lubię używać ekranu, aby to utrzymać. Obecnie mam zdalny forward, który działa od tygodni.

Przykład, zaczynając lokalnie:

screen
ssh -R ......

Kiedy zdalny forward jest zastosowany i masz powłokę na zdalnym komputerze:

screen
Ctrl + a + d

Masz teraz nieprzerwane zdalne przekierowanie. Sztuczka polega na tym, aby uruchomić screen na obu końcach

1
1
1
2015-07-30 14:02:55 +0000

Ostatnio sam miałem ten problem, ponieważ te rozwiązania wymagają ponownego wprowadzenia hasła za każdym razem, jeśli używasz logowania za pomocą hasła, użyłem sshpass w pętli wraz z monitem tekstowym, aby uniknąć posiadania hasła w pliku wsadowym.

Pomyślałem, że podzielę się moim rozwiązaniem na tym thead na wypadek, gdyby ktoś inny miał ten sam problem:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh user@address -p port
    sleep 1
done
1
1
1
2009-09-08 14:09:33 +0000

podczas gdy istnieją narzędzia takie jak autossh, które pomagają zrestartować sesję ssh… to co uważam za naprawdę przydatne to uruchomienie polecenia ‘screen’. Pozwala ono wznowić sesje ssh nawet po rozłączeniu się. Szczególnie przydatne jeśli twoje połączenie nie jest tak niezawodne jak powinno być.

…nie zapomnij zaznaczyć, że jest to ‘poprawna’ odpowiedź, jeśli ci to pomoże k! ;-)

1
1
1
2009-09-08 13:17:28 +0000

Miałem potrzebę długoterminowego utrzymywania tunelu SSH. Moje rozwiązanie działało z serwera Linux, i jest to po prostu mały program C, który respawnuje ssh używając uwierzytelniania opartego na kluczach.

Nie jestem pewien co do zawieszania się, ale miałem tunele umierające z powodu timeoutów.

Bardzo chciałbym udostępnić kod respawnera, ale nie mogę go teraz znaleźć.

0
0
0
2017-07-15 00:04:11 +0000

Ponieważ autossh nie spełnia naszych potrzeb (istnieje z błędem, jeśli nie może połączyć się z serwerem przy pierwszej próbie), napisaliśmy czystą aplikację bashową: https://github.com/aktos-io/link-with-server

Tworzy ona domyślnie odwrotny tunel dla portu sshd NODE'a (22) na serwerze. Jeśli potrzebujesz wykonać jakieś inne czynności (jak przekierowanie dodatkowych portów, wysyłanie maili przy połączeniu, itp…) możesz umieścić swoje skrypty w folderach on-connect i on-disconnect.

0
0
0
2009-09-28 10:27:21 +0000

Miałem podobne problemy z moim poprzednim dostawcą usług internetowych. U mnie było tak samo z każdym połączeniem tcp, odwiedzaniem stron internetowych czy wysyłaniem poczty.

Rozwiązaniem było skonfigurowanie połączenia VPN przez UDP (używałem OpenVPN). To połączenie było bardziej tolerancyjne na to, co powodowało rozłączenia. Następnie możesz uruchomić dowolną usługę poprzez to połączenie.

Nadal mogą wystąpić problemy z połączeniem, ale ponieważ tunel będzie bardziej tolerancyjny, każda sesja ssh będzie odczuwać krótkie wstrzymanie, a nie zostanie rozłączona.

Aby to zrobić, będziesz potrzebował usługi VPN online, którą możesz skonfigurować na własnym serwerze.

0
0
0
2020-02-20 15:09:46 +0000

Możesz bardzo prosto użyć komendy tmux na swoim zdalnym serwerze. Pozwala to na otwarcie “sesji” na zdalnej maszynie, gdzie będziesz uruchamiał swój zdalny kod.

Następnie możesz opuścić (lub stracić połączenie w twoim przypadku) zdalną maszynę bez obaw, biorąc pod uwagę, że twój kod jest bezpiecznie uruchomiony w sesji tmux.

Wreszcie, kiedy ponownie połączysz się na zdalnym serwerze, musisz tylko tmux attach wrócić do sesji, którą miałeś wcześniej otwartą i to wszystko.