Отказ от ответственности

Отказ от ответственности

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

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

Я использую Ubuntu 14.04 LTS, редакцию MATE. Спасибо.

решение1

Вы можете рассмотреть использование mosh:https://mosh.org/

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

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

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

решение2

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

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

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

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

Таким образом, если вы установите ServerAliveIntervalзначение 5, sshсоединение будет автоматически отключено, если сеть прервется на 15 секунд.

решение3

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

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

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

Если это актуально, я делаю все это с помощьюterminatorкак эмулятор терминала.

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

sudo apt-get install tmux terminator byobu

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

решение4

Отказ от ответственности

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

Подробности смотрите ниже. В любом случае:

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

Создайте скрипт оболочки, подобный этому:

#!/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, например, «у вас просто не включен Wi-Fi» или что-то в этом роде, но для вас это, вероятно, не имеет значения.

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

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

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

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

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

Подробности

Как sshобычно восстанавливается

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Связанный контент