Экран или аналогичный, для автоматического возобновления нестабильного соединения SSH

18

Мне часто приходится подключаться к серверу через SSH в ненадежной среде Wi-Fi. На сервере я запускаю screen, поэтому, если я отсоединяюсь, я могу снова подключиться и возобновить сеанс экрана, а также продолжить с того места, на котором остановился, но потеря соединения все еще является основным приемником времени: если соединение прерывается, пока я Нахожусь на сервере, окно терминала имеет тенденцию зависать. Мне нужно убить эту вкладку, открыть новую, снова подключиться к серверу по ssh и возобновить сеанс экрана. Я пробовал это с запущенным экраном на сервере и экраном локально. В любом случае он имеет тенденцию зависать, когда соединение прекращается.

Есть ли какой-нибудь способ, которым у меня может быть что-то похожее на экран, или, может быть, сам экран, который будет автоматически пытаться повторно подключиться и поддерживать сеанс, так что мне не нужно продолжать повторное подключение вручную? Часто, когда я теряю связь, я думаю, что это только на очень короткий период - может быть, меньше секунды.

Я использую Ubuntu 14.04 LTS, выпуск MATE. Благодарность

Макс Уильямс
источник
4
«Окно оболочки имеет тенденцию зависать»: это потому, что ваш локальный ssh ​​не знает, что соединение не работает. Нажмите <Enter>и напечатайте, ~.чтобы сообщить своей стороне, что нужно разорвать соединение, и вы можете просто повторить последнюю команду ssh для повторного соединения (например, с помощью стрелки вверх или !!).
Алексис
@alexis, это звучит как более быстрый способ переподключения, спасибо! Я хотел бы, чтобы это произошло автоматически, хотя ...
Макс Уильямс

Ответы:

23

Вы можете посмотреть, используя mosh: https://mosh.org/

Вы можете настроить сервер «Jump» с надежным подключением к Интернету, к которому вы moshподключаетесь, и затем проводить sshсеансы на каждом сервере, которым вы управляете. Причина, по которой я предлагаю использовать сервер переходов, заключается в том, что вы можете не устанавливать moshсерверы, которыми вы управляете.

Еще одним преимуществом moshявляется то, что он основан на UDP, а не на TCP, и ваш сеанс может выдержать изменение IP-адреса, например, при переходе от WiFi к мобильному интернет-соединению.

Просто чтобы прояснить, moshэто не замена screen, а скорее ssh. Это все еще хорошая идея для использования screenс ним, так как moshсам по себе не предоставляет способ восстановить соединение с вашим сеансом, если клиент по какой-то причине умирает.

ржавый Шеклфорд
источник
Спасибо, это всего лишь один сервер (большую часть времени), и мы владеем им, поэтому я должен иметь возможность установить Mosh. Я проверю это.
Макс Уильямс
На самом деле получается, что поскольку наш сервер довольно старый (или работает со старой Ubuntu, я должен сказать), его слишком сложно установить. :(
Макс Уильямс
@MaxWilliams сколько лет? Даже LTS 12.4 вышел из поддержки. И почему бы просто не попытаться скомпилировать его самостоятельно
phuclv
Когда я читаю документацию по mosh, вам нужен mosh-сервер на каждом хосте, которым вы собираетесь удаленно управлять. Тем не менее, безусловно, интересно.
Wildcard
1
Подключение к терминалу tmux через mosh - самое стабильное решение для меня.
Немо
3

Я использую tmuxв течение нескольких лет, и по моему опыту, он подключается автоматически. По крайней мере, когда соединение обрывается только в течение относительно короткого времени. Обратите внимание, что я на самом деле использую byobutmux в качестве бэкэнда. Я не знаю , если это надежность является признаком tmuxили byobuдаже комбинации из двух, но я предлагаю вам как попробовать.

Я подключаюсь из локальной установки Arch к различным удаленным серверам Ubuntu через VPN. Я только что проверил это, отключив сетевой кабель, когда я был подключен к удаленному. Сеанс завис, но как только мой кабель был снова подключен, он возобновился без проблем.

Однако, когда я проверил, перезапустив мой маршрутизатор, соединение не вернулось. Я предполагаю, что это как-то связано с тем, как долго сеть была отключена, но, похоже, она снова подключается, если она не работает всего несколько секунд.

В случае, если это уместно, я делаю все это используя terminatorмой эмулятор терминала.

Все три доступны в репозиториях Ubuntu:

sudo apt-get install tmux terminator byobu

Тем не менее, я совсем не уверен, что tmuxили byobuлучше справляюсь с ssh-отключениями. Я только знаю, что по своему опыту они часто возвращаются из-за коротких потерь связи. Это может быть связано с другими аспектами моей конфигурации, хотя.

Тердон
источник
1
При перезапуске маршрутизатора вам, возможно, был присвоен другой публичный IP-адрес, который разорвал tcpсоединение. Исходя из моего опыта, я sshмогу быть очень устойчивым к периодическим пропаданиям в сети, я не думаю, что это имеет какое-либо отношение к тому факту, что вы используете tmuxвнутри sshокна.
ржавый Шеклфорд
3
Я собирался сказать то же самое: даже с обычным SSH, вы можете иметь дело с коротким разъединением, пока не прервется соединение TCP. Что может произойти, если ваш интерфейс отключается, или какой-то чрезмерный маршрутизатор убивает его (маршрутизаторы NAT могут забыть о состоянии NAT при перезагрузке и разорвать существующие соединения), или ClientAlive/ ServerAliveзапускает, или ... Я не знаю, что byobuделает, хотя ,
ilkkachu
Да, но OP, кажется, испытывает зависание при любом сбое соединения, а я нет. Но да, вы правы, я также вижу это с простым ssh и без tmux. Тем не менее, может быть, экран не может справиться с этим?
Тердон
2
Да , да, @MaxWilliams tmux- это более современная альтернатива screen. Когда я впервые начал работать так, как я делаю сейчас, и нуждался в такого рода вещах, мое беглое чтение показало, что tmuxэто лучший выбор в наши дни. Я также не уверен на 100%, что он лучше справляется с потерянными соединениями, все, что я знаю, это то, что он восстанавливается после кратковременных отключений в моем опыте. Будь то до tmuxили что-то еще, я не знаю. Но, похоже, стоит попробовать :). Byobu - это в основном интерфейс для screen / tmux, а не эмулятор терминала с графическим интерфейсом. Это чрезвычайно полезно, хотя: byobu.org
Тердон
2
tmux ничего не делает с прерываниями соединения. Работает с терминальным устройством, предоставленным ssh. Все стоит и падает с подключением ssh.
Йонас Шефер
2

Используйте параметры ssh, ServerAliveчтобы определить, когда произошел сбой соединения.

ServerAliveCountMax
Устанавливает количество живых сообщений сервера (см. Ниже), которые могут быть отправлены без ssh (1) получения каких-либо сообщений от сервера. Если этот порог достигнут, когда отправляются живые сообщения сервера, ssh отключится от сервера, завершив сеанс. Важно отметить, что использование живых сообщений на сервере сильно отличается от TCPKeepAlive (ниже). Живые сообщения сервера отправляются через зашифрованный канал и, следовательно, не будут подделаны. Опция keepalive TCP, включаемая TCPKeepAlive, подделывается. Механизм работы сервера полезен, когда клиент или сервер зависят от знания, когда соединение стало неактивным.

Значение по умолчанию - 3. Если, например, для ServerAliveInterval (см. Ниже) установлено значение 15, а для параметра ServerAliveCountMax оставлено значение по умолчанию, если сервер перестает отвечать на запросы, ssh отключится примерно через 45 секунд.

ServerAliveInterval
Устанавливает интервал ожидания в секундах, после которого, если данные не были получены от сервера, ssh (1) отправит сообщение через зашифрованный канал, чтобы запросить ответ от сервера. По умолчанию 0, что означает, что эти сообщения не будут отправлены на сервер.

Поэтому, если вы установите ServerAliveInterval5, sshавтоматически отключится, если сеть отключится на 15 секунд.

Barmar
источник
Чтобы прервать сессию SSH силой, я нажимаю ~.(или сначала Enter, затем ~.), состоящую из: escape-символа ~и команды прервать сессию.
imz - Иван Захарящев
@ imz - IvanZakharyaschev Предполагается, что вы можете сказать, что соединение прервано. Использование поддержки активности SSH автоматически обнаружит сбой.
Бармар
Это звучит очень полезно, спасибо, я обязательно попробую, когда в следующий раз буду в «хлопьевидной зоне».
Макс Уильямс
@ Бармар Да, правда. Я также подумал о проблеме определения, действительно ли соединение зависло, или, если я нажму что-либо, я могу случайно отправить эти ключи на удаленную сторону ... И я не знаю хорошего решения.
imz - Иван Захарящев
2

В подобных условиях я склонен использовать eshellс TRAMP (поверх ssh) внутри Emacs. TRAMP заботится о повторном подключении, когда это необходимо, не доставляя мне особых хлопот, давая необходимые команды для удаленной оболочки.

Однако eshell не годится в качестве терминала, т. Е. Для запуска команд, которые выполняют с терминалом что-то особенное или которые выполняются в течение значительного периода времени, непрерывно (постепенно) распечатывая что-либо.

По сути, довольно просто начать использовать его в Emacs с TRAMP:

M-x eshell
cd /user@host:
imz - Иван Захарящев
источник
1

отказ

Если ваше SSH-соединение не выдерживает кратковременных перебоев в работе сети, то происходит что- то еще, что не позволяет sshи TCP делает свое обычное дело.

Смотрите ниже для деталей. Тем не мение:

Самое быстрое и самое грязное решение без зависимостей

Создайте скрипт оболочки следующим образом:

#!/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"

Это просто запустит тупо-простой цикл, который продолжает пытаться соединиться sshи присоединиться к нему screen. Передайте хост или что-то еще, что вы обычно передаете на вашssh вызову в качестве аргументов командной строки.

Переподключение основано только на том, сообщает ли SSH об ошибке соединения, что означает, что у него нет интеллекта для обнаружения ошибок, не связанных с SSH, таких как «буквально у вас не включен WiFI» или что-то подобное, но это, вероятно, не имеет значения для вы.

Я предполагаю, что у вас есть ssh-agentили SSH-ключ без парольной фразы, который позволит переподключаться просто без дополнительной информации от вас.

Будет крошечное состояние гонки, при котором, если вы нажмете в ^Cтечение невидимой для человека доли секунды во время переподключения, вы можете в конечном итоге убить скрипт, вместо того, чтобы пропустить его ^Cчерез клиентский терминал, поэтому, если вы подозреваете, что соединение зависло не пюре^C слишком усердно

Самое простое дополнительное программное решение

Вы можете попробовать программу autossh , которая должна быть доступна в вашем хранилище пакетов Ubuntu.

Если вам нужно собрать из исходного кода или проверить его, это отдельная программа на C, которая компилируется без каких-либо дополнительных библиотек в качестве зависимостей, кажется, имеет больше интеллекта для проверки живости соединения, чем мой хак выше, и она также поставляется с удобной rscreenкомандой сценария, которая автоматически Прикрепляет к screen.

Детали

Как sshнормально восстанавливается

Просто чтобы проверить, потому что я не люблю говорить вещи, не проверяя себя, я провел небольшой тест, прежде чем ответить:

Я подключился к WiFi с помощью устройства Linux, установил SSH-соединение с другим устройством в локальной сети, проверил, что у меня есть рабочее sshсоединение с другим концом (может выполнять команды и т. Д.), Затем на клиенте отключил WiFi (что вызвало интерфейс чтобы быть деконфигурированным: больше никаких IP-адресов), набрал в сессию ssh еще больше символов (конечно, без ответа), а затем снова подключился к моему WiFi - переподключение действительно не удалось хотя бы один раз из-за плохого сигнала и других факторов затем снова подключился: я подождал около пяти секунд для восстановления sshсеанса, ничего не произошло, поэтому я нажал еще одну клавишу, и sshсеанс сразу же ожил, и все ключи, которые я набрал во время разъединения, появились в командной строке.

Видите, sshпросто пишет / читает в сетевой сокет TCP, пока ОС не скажет, что что-то пошло не так, и TCP на самом деле очень терпим к длительным сбоям соединения.

Оставшись на своих собственных устройствах с настройками ядра по умолчанию, стек TCP в Linux с радостью допустит, что соединение будет совершенно бесшумным в течение многих минут, прежде чем объявить соединение разорванным и сообщить об ошибке ssh- к тому времени, когда оно, наконец, сдается, мы разговариваем на площадке. ~ 30 минут, или, по крайней мере, определенно достаточно долго, чтобы пережить икоты соединения, продолжающиеся секунду или минуту.

Под покровом стек Linux TCP постепенно повторяет сообщения с более длительными и более длительными задержками, однако это означает, что к тому времени, когда ваше соединение действительно возвращается, вы, возможно, наблюдаете дополнительную задержку, прежде чем ваш sshсеанс снова станет «живым».

Почему это иногда ломается

Часто что-то активно заставляет соединение закрываться после некоторого значительно более короткого периода бездействия, чем допустимый для стека TCP, и затем не сообщает об этом состоянии соединения вашему sshклиенту.

Вероятные кандидаты включают в себя:

  1. Брандмауэры или маршрутизаторы NAT, которые должны использовать память для запоминания каждого живого TCP-соединения - в качестве оптимизации и некоторых мер по предотвращению атак DOS, они иногда просто забывают ваше соединение, а затем молча игнорируют последующие пакеты для него, потому что пакеты в середина соединения, когда вы не помните, что существующее соединение выглядит недействительным.

  2. Брандмауэры / маршрутизаторы с лучшим поведением будут внедрять пакет TCP RST, который обычно проявляется в виде connection reset by peerсообщения об ошибке, но пакет сброса - «забыл и забыл», поэтому, если соединение с вашим клиентом все еще имеет проблемы в этот момент, и сбрасывает сбросить пакет тоже, ваш клиент будет думать, что соединение еще живо.

  3. Сервер сам может иметь политику брандмауэра молчаливо опускаете неожиданные пакеты, которые будут ломаются попытки подключения возобновления клиента всякий раз , когда сервер считает , что соединение закрыто , но клиент не будет : ваш клиент продолжает пытаться продолжить соединение, а сервер просто игнорируя его, потому что нет живого соединения, которому эти пакеты принадлежат в состоянии брандмауэра сервера.

    Поскольку вы работаете в Linux, внимательно проверьте iptables/ ip6tables(или, nftесли вы используете новый материал) вашего сервера, что именно вы разрешаете, а не отбрасываете. Очень часто разрешают новые / установленные / связанные пакеты на TCP-порту TCP SSH, но не «недействительные» - если вы молча отбрасываете все, что не разрешено, эта общая установка может вызвать такие зависания после кратких проблем с подключением ,

  4. Ваш SSH-сервер может быть настроен на закрытие соединения после определенного периода бездействия, используя один из параметров OpenSSH для пакетов поддержки активности клиента TCP или SSH. Само по себе это не вызовет неопределенных зависаний, но может поставить вас в одно из состояний, описанных выше.

  5. Возможно, вы просто не даете ему достаточно времени, чтобы «развязать» его самостоятельно, после того как вы попали в состояние, в котором ваш sshсеанс зависает.

mtraceur
источник