Screen lub podobny do automatycznego wznawiania niestabilnego połączenia ssh

18

Często muszę łączyć się z serwerem przez ssh w niewiarygodnym środowisku Wi-Fi. Na serwerze uruchamiam ekran, więc jeśli się rozłączę, mogę ponownie połączyć się i wznowić sesję ekranu, i wybrać miejsce, w którym zostało przerwane, ale utrata połączenia nadal jest poważnym utratą czasu: jeśli połączenie zostanie przerwane podczas Jestem na serwerze, okno terminala ma tendencję do zawieszania się. Muszę zabić tę kartę, otworzyć nową, ponownie ssh na serwer i wznowić sesję ekranową. Próbowałem tego z uruchomionym ekranem na serwerze i ekranie lokalnym. Tak czy inaczej, ma tendencję do zawieszania się, gdy połączenie zostanie przerwane.

Czy jest jakiś sposób, aby uzyskać coś podobnego do ekranu, a może sam ekran, który automatycznie spróbuje połączyć się ponownie i utrzyma sesję w ruchu, więc nie będę musiał ponownie ręcznie się łączyć? Często kiedy tracę połączenie, myślę, że to tylko na bardzo krótki okres - może mniej niż sekundę.

Używam Ubuntu 14.04 LTS, edycja MATE. dzięki

Max Williams
źródło
4
Re „okno powłoki ma tendencję do zawieszania się”: To dlatego, że lokalny ssh nie wie, że połączenie nie działa. Naciśnij <Enter>i wpisz, ~.aby powiedzieć swojej stronie, aby porzuciła połączenie, a następnie możesz po prostu powtórzyć ostatnie polecenie ssh, aby połączyć się ponownie (np. Za pomocą strzałki w górę lub !!).
Alexis
@alexis, który brzmi jak szybszy sposób na ponowne połączenie, dzięki! Chciałbym, żeby stało się to automatycznie ...
Max Williams

Odpowiedzi:

23

Możesz spojrzeć na użycie mosh: https://mosh.org/

Możesz skonfigurować „skaczący” serwer z niezawodnym połączeniem internetowym, którego używasz moshdo łączenia się, a następnie przeprowadzania sshsesji z każdym zarządzanym serwerem. Powodem, dla którego sugeruję użycie serwera skoku jest to, że możesz nie chcieć instalować moshna serwerach, którymi zarządzasz.

Kolejną zaletą moshjest to, że opiera się na UDP zamiast na TCP, a twoja sesja może przetrwać zmianę adresu IP, na przykład przejście z Wi-Fi na mobilne połączenie internetowe.

Żeby było jasne, moshnie jest zamiennikiem screen, ale raczej ssh. Nadal dobrym pomysłem jest używanie screengo, ponieważ moshsam nie zapewnia sposobu ponownego połączenia się z sesją, jeśli klient umrze z jakiegoś powodu.

zardzewiały Shackleford
źródło
Dzięki, to tylko jeden serwer (przez większość czasu) i jesteśmy jego właścicielem, więc powinienem móc zainstalować Mosh. Sprawdzę to.
Max Williams
W rzeczywistości okazuje się, że ponieważ nasz serwer jest dość stary (lub działający stary Ubuntu, powinienem powiedzieć), instalacja jest zbyt trudna. :(
Max Williams
@MaxWilliams ile to lat? Nawet LTS 12.4 przestał być obsługiwany. A może po prostu spróbuj samemu go skompilować
phuclv
Gdy czytam dokumenty mosh, potrzebujesz serwera mosh na każdym hoście, którym zamierzasz zarządzać zdalnie. Mimo to zdecydowanie interesujące.
Wildcard
1
Połączenie z terminalem tmux przez mosh jest dla mnie najbardziej stabilnym rozwiązaniem.
Nemo
3

Używam od tmuxkilku lat i z mojego doświadczenia, łączy się automatycznie. Przynajmniej gdy połączenie nie powiedzie się tylko przez stosunkowo krótki czas. Zauważ, że faktycznie używam byobuz tmux jako backend. Nie wiem, czy ta odporność jest cechą tmuxlub byobunawet kombinacji dwóch, ale proponuję dać zarówno spróbować.

Łączę się z mojej lokalnej instalacji Arch do różnych zdalnych serwerów Ubuntu przez VPN. Właśnie to przetestowałem, odłączając kabel sieciowy, gdy byłem podłączony do pilota. Sesja zawiesiła się, ale gdy tylko kabel został ponownie podłączony, wznowił się bezproblemowo.

Jednak podczas testowania przez ponowne uruchomienie routera połączenie nie powróciło. Zakładam, że ma to coś wspólnego z tym, jak długo sieć była nieczynna, ale wydaje się, że łączy się ponownie, jeśli jest wyłączona tylko przez kilka sekund.

W razie potrzeby robię to wszystko terminatorjako mój emulator terminala.

Wszystkie trzy są dostępne w repozytoriach Ubuntu:

sudo apt-get install tmux terminator byobu

Jednak nie jestem wcale pewien, czy tmuxalbo byobulepiej radzę sobie z rozłączeniami ssh. Wiem tylko, że z mojego doświadczenia wynika, że ​​często wracają z krótkich strat w połączeniach. Może to wynikać z innych aspektów mojej konfiguracji.

terdon
źródło
1
Po ponownym uruchomieniu routera możesz otrzymać inny publiczny adres IP, co spowoduje zerwanie tcppołączenia. Z mojego doświadczenia sshwynika, że ​​może być bardzo odporny na przerywane przerwy w sieci, nie sądzę, aby miało to związek z faktem, że używasz go tmuxw sshoknie.
zardzewiały shackleford
3
Chciałem powiedzieć to samo: nawet przy zwykłym SSH możesz poradzić sobie z krótkim rozłączeniem, o ile połączenie TCP nie zostanie przerwane. Co może się zdarzyć, jeśli twój interfejs zostanie zamknięty lub jakiś nadgorliwy router go zabije (routery NAT mogą zapomnieć o stanie NAT przy ponownym uruchomieniu i przerwać istniejące połączenia), ClientAlive/ / ServerAlivewyzwalaczy lub ... Nie mam pojęcia, co to byoburobi .
ilkkachu
Tak, ale wydaje się, że OP doświadcza zawieszania się przy każdym niepowodzeniu połączenia, podczas gdy ja nie. Ale tak, masz rację, widzę to również z prostym ssh i bez tmux. Niemniej jednak może ekran nie może sobie z tym poradzić?
terdon
2
@ MaxWilliams tmuxjest w zasadzie bardziej nowoczesną alternatywą dla screentak. Kiedy zacząłem pracować tak jak teraz i potrzebowałem tego rodzaju rzeczy, moja pobieżna lektura sugerowała, że tmuxjest to obecnie lepszy wybór. Nie jestem też w 100% pewien, że lepiej zarządza utraconymi połączeniami, wszystko, co wiem, to powrót do zdrowia po krótkich przestojach z mojego doświadczenia. Czy to w dół, tmuxczy coś innego, nie wiem. Ale warto spróbować :). Byobu jest w zasadzie nakładką na screen / tmux, a nie emulatorem terminala GUI. Jest to jednak niezwykle przydatne: byobu.org
terdon
2
tmux nie robi nic na temat przerw w połączeniu. Działa z urządzeniem końcowym dostarczonym przez ssh. Wszystko stoi i spada z połączeniem ssh.
Jonas Schäfer
2

Użyj ServerAliveopcji ssh, aby wykryć niepowodzenie połączenia.

ServerAliveCountMax
Ustawia liczbę żywych komunikatów serwera (patrz poniżej), które mogą zostać wysłane bez ssh (1) odbierającego jakiekolwiek wiadomości z powrotem z serwera. Jeśli ten próg zostanie osiągnięty podczas wysyłania komunikatów o aktywności serwera, ssh rozłączy się z serwerem, kończąc sesję. Ważne jest, aby pamiętać, że użycie komunikatów o aktywności serwera różni się znacznie od TCPKeepAlive (poniżej). Żywe wiadomości serwera są wysyłane zaszyfrowanym kanałem, dlatego nie będą sfałszowane. Opcja utrzymywania aktywności TCP włączona przez TCPKeepAlive jest sfałszowana. Mechanizm aktywnego serwera jest cenny, gdy klient lub serwer polegają na wiedzy, kiedy połączenie staje się nieaktywne.

Wartość domyślna to 3. Jeśli na przykład ServerAliveInterval (patrz poniżej) jest ustawiony na 15, a ServerAliveCountMax pozostanie domyślnie, jeśli serwer przestanie odpowiadać, ssh rozłączy się po około 45 sekundach.

ServerAliveInterval
Ustawia limit czasu w sekundach, po upływie którego nie otrzymano żadnych danych z serwera, ssh (1) wyśle ​​wiadomość przez zaszyfrowany kanał z prośbą o odpowiedź z serwera. Wartość domyślna to 0, co oznacza, że ​​te wiadomości nie będą wysyłane na serwer.

Jeśli więc wybierzesz wartość ServerAliveInterval5, sshnastąpi automatyczne rozłączenie, jeśli sieć wyłączy się przez 15 sekund.

Barmar
źródło
Aby przerwać sesję SSH siłą, naciskam ~.(lub najpierw Enter, a następnie ~.) składający się z: znaku ucieczki ~i polecenia przerwania sesji.
imz - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Zakłada, że ​​możesz powiedzieć, że połączenie zostało zawieszone. Użycie zabezpieczenia SSH automatycznie wykryje awarię.
Barmar
Brzmi naprawdę przydatnie, dzięki, zdecydowanie spróbuję następnym razem, gdy będę w „strefie niestabilności”.
Max Williams
@Barmar Tak, prawda. Pomyślałem także o problemie z ustaleniem, czy połączenie jest naprawdę zawieszone, czy też naciśnięcie czegoś może przypadkowo wysłać te klucze do zdalnej strony ... I nie znam dobrego rozwiązania.
imz - Ivan Zakharyaschev
2

W podobnych warunkach zwykle używam eshellTRAMP (over ssh) w Emacsie. TRAMP zajmuje się ponownym łączeniem, gdy jest to konieczne, bez powodowania większych problemów dla mnie, dając pożądane polecenia dla zdalnej powłoki.

Jednak eshell nie jest dobry jako terminal, tj. Do uruchamiania poleceń, które robią coś specjalnego z terminalem, lub które działają przez znaczny okres ciągłego (przyrostowego) drukowania czegoś.

Zasadniczo korzystanie z niego w Emacsie z TRAMP jest dość proste:

M-x eshell
cd /user@host:
imz - Ivan Zakharyaschev
źródło
1

Zrzeczenie się

Jeśli twoje połączenie SSH nie przeżywa krótkotrwałych awarii sieci, dzieje się coś innego , co nie pozwala sshi TCP wykonuje swoje normalne czynności.

Szczegóły poniżej. Tak czy siak:

Najszybsze i najbrudniejsze rozwiązanie bez zależności

Utwórz skrypt powłoki w następujący sposób:

#!/bin/sh -

# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'

# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255

# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
    ssh $timeout_options -t "$@" screen -dR
    status=$?
    # You can add a `sleep` command here or a counter or whatever
    # you might need as far as rate/retry limiting.
done
exit "$status"

To po prostu uruchomi głupią, prostą pętlę, która wciąż próbuje się połączyć sshi dołączyć screen. Przekaż hosta lub cokolwiek innego, co normalnie przekażesz do sshwywołania, jako argumenty wiersza polecenia.

Ponowne połączenie opiera się tylko na tym, czy SSH zgłasza błąd połączenia, co oznacza, że ​​nie ma inteligencji w wykrywaniu błędów innych niż SSH, takich jak „dosłownie nie masz włączonego WiFI” lub cokolwiek innego, ale to prawdopodobnie nie ma znaczenia dla ty.

Zakładam, że masz ssh-agentklucz SSH bez hasła, który pozwoli, aby ponowne połączenia działały bez dodatkowych danych wejściowych.

Będzie mały warunek wyścigu, w którym jeśli trafisz ^Cpodczas właściwej niedostrzegalnej dla człowieka części sekundy podczas ponownego połączenia, możesz skończyć zabiciem skryptu zamiast przekazywania go ^Cdo terminalu klienta, więc jeśli podejrzewasz, że połączenie się zawiesiło nie zacieraj ^Czbyt gorliwie.

Najprostsze dodatkowe oprogramowanie

Możesz wypróbować program autossh , który powinien być dostępny w repozytorium pakietów Ubuntu.

Jeśli musisz zbudować go ze źródła lub skontrolować, jest to pojedynczy program C, który kompiluje się bez żadnych dodatkowych bibliotek jako zależności, wydaje się mieć więcej inteligencji w sprawdzaniu żywotności połączenia niż mój hack powyżej, a także jest wyposażony w wygodne rscreenpolecenie skryptowe, które automatycznie dołącza się do screen.

Detale

Jak sshnormalnie odzyskuje

Aby zweryfikować, bo nie lubię mówić rzeczy bez sprawdzenia siebie, przed odpowiedzią przeprowadziłem mały test:

Włączyłem WiFi z urządzeniem Linux, nawiązałem połączenie SSH z innym urządzeniem w mojej sieci LAN, zweryfikowałem, że mam działające sshpołączenie z drugim końcem (mogłem uruchamiać polecenia itp.), A następnie na kliencie odłączyłem Wi-Fi (powodując interfejs do zdekonfigurowania: nie ma już adresów IP), wpisałem kilka kolejnych znaków do sesji ssh (oczywiście bez odpowiedzi), a następnie ponownie połączyłem się z moją siecią Wi-Fi - ponowne połączenie nie powiodło się przynajmniej raz z powodu złego sygnału i innych czynników , a potem w końcu ponownie się połączyłem: czekałem około pięciu sekund na sshprzywrócenie sesji, nic się nie stało, więc nacisnąłem jeszcze jeden klawisz, a sshsesja natychmiast ożyła, a wszystkie klawisze, które wpisałem podczas rozłączania, pojawiły się w wierszu polecenia.

Widzisz, sshpo prostu zapisuje / odczytuje w gnieździe sieciowym TCP, dopóki system operacyjny nie powie, że coś poszło nie tak, a TCP jest w rzeczywistości bardzo tolerancyjny na przedłużające się zerwanie połączenia.

Pozostawiony swoim własnym urządzeniom z domyślnymi ustawieniami jądra, stos TCP w Linuksie z radością toleruje połączenie, które zostanie całkowicie uciszone na wiele minut, zanim zadeklaruje połączenie jako martwe i zgłosi błąd ssh- zanim w końcu się podda, rozmawiamy na boisku ~ 30 minut, a przynajmniej na pewno wystarczająco długo, aby przetrwać czkawkę połączenia trwającą sekundę lub minutę.

Jednak pod osłonami stos Linux Linux stopniowo próbuje wiadomości z coraz dłuższymi opóźnieniami, co oznacza, że ​​zanim połączenie zostanie przywrócone, możesz spodziewać się dodatkowego opóźnienia, zanim sshsesja znów zacznie „ożywać”.

Dlaczego czasami się psuje

Często coś aktywnie powoduje zamknięcie połączenia po znacznie krótszym okresie bezczynności niż ilość tolerowana przez stos TCP, a następnie niezgłoszenie sshklientowi tego stanu połączenia .

Prawdopodobni kandydaci to:

  1. Zapory ogniowe lub routery NAT, które muszą używać pamięci do zapamiętywania każdego połączenia TCP na żywo - jako optymalizacja i pewne ograniczenie przed atakami DOS czasami po prostu zapominają o twoim połączeniu, a następnie dyskretnie ignorują kolejne pakiety, ponieważ pakiety w środek połączenia, gdy nie pamiętasz istniejącego połączenia, wygląda nieprawidłowo.

  2. Lepiej działające zapory ogniowe / routery wstrzykną pakiet TCP RST, który zwykle objawia się jako connection reset by peerkomunikat o błędzie, ale pakiet resetowania jest zapisem i zapomnieniem, więc jeśli połączenie z klientem nadal ma problemy w tym momencie i upuszcza zresetuj też pakiet, twój klient będzie myślał, że połączenie jest nadal aktywne.

  3. Serwer sam może posiadać politykę zapory cicho upuść nieoczekiwane pakiety, które rozkładają wznawia połączenie prób klienta, gdy serwer myśli połączenie zamknięte, ale klient nie: klient utrzymuje próbuje kontynuować połączenie, ale serwer jest po prostu ignorując to, ponieważ nie ma połączenia na żywo, do którego te pakiety należą w stanie zapory serwera.

    Ponieważ używasz Linuksa, dokładnie sprawdź na swoim serwerze iptables/ ip6tables(lub nftjeśli używasz nowych rzeczy) dokładnie, na co pozwalasz, a nie upuszczając. Bardzo często zezwala się na nowe / ustanowione / powiązane pakiety na porcie TCP SSH, ale nie na „niepoprawne” - jeśli po cichu upuszczasz wszystko, co nie jest dozwolone, ta wspólna konfiguracja może powodować tego rodzaju zawieszanie się po krótkich problemach z połączeniem .

  4. Sam serwer SSH może zostać skonfigurowany do zamykania połączenia po pewnym okresie bezczynności, przy użyciu jednej z opcji OpenSSH dla pakietów podtrzymujących klienta TCP lub SSH. Samo w sobie nie spowoduje to zawieszania się na czas nieokreślony, ale może wprowadzić cię w jeden ze stanów opisanych powyżej.

  5. Możliwe, że po prostu nie masz wystarczająco dużo czasu na samodzielne „odczepienie” po przejściu w stan, w którym kończy się sshsesja.

mtraceur
źródło