Как надежно сохранить SSH-туннель открытым?

Я использую SSH-туннель из работы, чтобы обойти различные идиотские брандмауэры (это нормально с моим боссом :)). Проблема в том, что через некоторое время соединение ssh обычно зависает, а туннель прерывается.

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

Бонусные баллы для тех, кто может сказать мне, как предотвратить мое свидание ssh, конечно!

199 голосов | спросил Peltier 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2009 17:04:22 +0400 2009, 17:04:22

15 ответов


239

Похоже, вам нужен autossh . Это будет контролировать туннель ssh и перезапустить его по мере необходимости. Мы использовали его в течение нескольких лет, и, похоже, он работает хорошо.

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

Подробнее о параметре -M здесь

ответил KeithB 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2009 17:43:51 +0400 2009, 17:43:51
33

Все брандмауэры stateful забывают о соединении после того, как не видели пакет для этого соединения в течение некоторого времени (чтобы таблицы состояний не заполнились соединениями, где оба конца умерли, не закрывая соединение). Большинство реализаций TCP отправляют пакет keepalive через долгое время без прослушивания с другой стороны (2 часа - это общее значение). Если, однако, существует брандмауэр с состоянием, который забывает о соединении, прежде чем пакеты keepalive могут быть отправлены, долговременное, но незанятое соединение умрет.

Если это так, решение состоит в том, чтобы предотвратить простоя соединения. OpenSSH имеет опцию ServerAliveInterval , которая может использоваться для предотвращения подключения от длительного простоя (в качестве бонуса он обнаружит, когда сверстник умер раньше, даже если соединение простаивает).

ответил CesarB 28 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 28 Sep 2009 17:47:26 +0400 2009, 17:47:26
22

На вашей собственной машине mac или linux настройте свой ssh, чтобы сервер ssh был жив каждые 3 минуты. Откройте терминал и запустите свой невидимый .ssh в своем доме:

  cd ~ /.ssh /
 

затем создайте файл конфигурации с 1 строкой с помощью:

  echo "ServerAliveInterval 180">>> конфиг
 

вы также должны добавить:

  ServerAliveCountMax xxxx (большое число)
 

значение по умолчанию равно 3, поэтому ServerAliveInterval 180 прекратит отправку через 9 минут (3 из 3-минутного интервала, указанного ServerAliveInterval).

ответил David Shaw 29 Maypm10 2010, 17:45:08
20

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

  while true
делать
  ssh <ssh_options> [Пользователь @] имя хоста
  спать 15
сделанный
 

Обратите внимание, что для этого требуется, чтобы ключевой файл устанавливал соединение автоматически, но это также относится к autossh.

ответил Jawa 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2009 18:58:15 +0400 2009, 18:58:15
9

Конечно, мне кажется, что вы все неправильно интерпретируете ServerAliveCountMax. Насколько я понимаю документы, это число активных сообщений сервера, которые могут оставаться без ответа без прекращения соединения. Поэтому в таких случаях, как мы обсуждаем здесь, установив его на высокое значение, вы просто убедитесь, что повесившееся соединение не будет обнаружено и прекращено!

Просто установить ServerAliveInterval должно быть достаточно, чтобы решить проблему с брандмауэром, забывшим о соединении, и оставляя ServerAliveCountMax низким, чтобы исходный конец заметил отказ и завершил работу, если соединение все равно не работает.

То, что вы хотите, 1) для того, чтобы соединение оставалось открытым постоянно при нормальных обстоятельствах, 2) для обнаружения отказа соединения и исходящей стороны для выхода из отказа и 3) для повторной выдачи команды ssh каждый раз, когда он выходит (как вы это делаете, это зависит от платформы, сценарий «while true», предложенный Jawa, является одним из способов, поскольку OS XI фактически настроил элемент launchd).

ответил user2793784 28 42013vEurope/Moscow11bEurope/MoscowThu, 28 Nov 2013 05:04:34 +0400 2013, 05:04:34
9

Всегда используйте параметр ServerAliveInterval SSH в случае, если проблемы туннеля создаются с помощью сеансов с истекшим NAT.

Всегда используйте метод респаунирования в случае, если соединение полностью опускается, у вас есть как минимум три варианта:

  • программа autosph
  • bash script ( while true do ssh ...; sleep 5; done ) не удаляет команду спящего режима, ssh может не работать быстро, и вы тоже будете респанировать многие процессы
  • /etc /inittab , чтобы иметь доступ к коробке, отправленному и установленному в другой стране, за NAT, без пересылки портов в поле, вы можете настроить его для создания туннеля ssh обратно к вам

      tun1: 2345: respawn: /usr /bin /ssh -i /path /to /rsaKey -f -N -o "ServerAliveInterval 180" -R 55002: localhost: 22 user @ publicip 'sleep 365d'
     
  • скрипт upstart на Ubuntu, где /etc /inittab недоступен:

      начать с net-device-up IFACE = eth0
    остановка на уровне выполнения [01S6]
    респаун
    предел респауна 180 900
    exec ssh -i /path /to /rsaKey -N -o "ServerAliveInterval 180" -R 55002: localhost: 22 user @ publicip
    пост-стоп-скрипт
        спать 5
    конец скрипта
     

или всегда используйте оба метода.

ответил claudiuf 9 MaramSun, 09 Mar 2014 01:30:40 +04002014-03-09T01:30:40+04:0001 2014, 01:30:40
8

Systemd идеально подходит для этого.

Создайте служебный файл /etc/systemd/system/sshtunnel.service , содержащий:

  [Unit]
Описание = SSH-туннель
После того, как = network.target

[Обслуживание]
Restart = всегда
RestartSec = 20
Пользователь = sshtunnel
ExecStart = /bin /ssh -NT -o ServerAliveInterval = 60 -L 5900: localhost: 5900 user @ otherserver

[Установить]
WantedBy = multi-user.target
 

(Модифицируйте команду ssh, чтобы она соответствовала)

  • это будет работать как пользователь sshtunnel , поэтому убедитесь, что пользователь существует первым
  • issue systemctl включить sshtunnel , чтобы он запускался во время загрузки
  • введите systemctl start sshtunnel , чтобы начать немедленно

Обновить январь 2018 : некоторые дистрибутивы (например, Fedora 27) могут использовать политику SELinux, чтобы предотвратить использование SSH из systemd init, и в этом случае потребуется настраиваемая политика для создания необходимых исключений.

ответил IanB 28 J000000Thursday16 2016, 09:10:14
6

Я решил эту проблему следующим образом:

Изменить

  ~ /.ssh /конфигурации
 

И добавьте

  ServerAliveInterval 15
ServerAliveCountMax 4
 

Согласно человек страница для ssh_config:

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

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

 ServerAliveInterval
         Устанавливает интервал ожидания в секундах, после которого, если нет данных
         был получен с сервера, ssh (1) отправит сообщение через
         зашифрованный канал для запроса ответа от сервера.
         по умолчанию - 0, что означает, что эти сообщения не будут отправляться
         сервер. Этот параметр применяется только к протоколу версии 2.
 
ответил nachopro 30 Maypm13 2013, 17:32:05
3

ExitOnForwardFailure yes является хорошим дополнением к другим предложениям. Если он подключается, но не может установить переадресацию порта, он просто бесполезен для вас, как если бы он вообще не подключался.

ответил jcomeau_ictx 7 J0000006Europe/Moscow 2015, 02:41:10
1

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

Я не уверен в подвеске, но у меня были туннели из-за тайм-аутов.

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

ответил baumgart 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2009 17:17:28 +0400 2009, 17:17:28
1

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

... не забудьте отметить это «правильный» ответ, если он поможет вам! ; -)

ответил koss 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2009 18:09:33 +0400 2009, 18:09:33
1

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

Пример: запуск локально:

  экран
ssh -R ......
 

Когда применяется удаленная переадресация, и у вас есть оболочка на удаленном компьютере:

  экран
Ctrl + a + d
 

Теперь у вас есть непрерывный удаленный доступ. Хитрость заключается в том, чтобы запускать экран с обоих концов.

ответил landypro 13 MarpmTue, 13 Mar 2012 16:11:18 +04002012-03-13T16:11:18+04:0004 2012, 16:11:18
1

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

Думаю, что я поделился бы своим решением на этом thead, если у кого-то еще будет такая же проблема:

  #! /Bin /Баш
read -s -p "Пароль:" пройти
тогда как true
делать
    sshpass -p "$ pass" ssh user @ address -p порт
    спать 1
сделанный
 
ответил Brainfloat 30 J000000Thursday15 2015, 17:02:55
0

У меня были аналогичные проблемы с моим предыдущим провайдером. Для меня это было одинаково с любым подключением tcp, посещением веб-сайтов или отправкой почты.

Решением было настроить VPN-соединение через UDP (я использовал OpenVPN). Это соединение было более терпимым к тому, что вызывало разъединения. Затем вы можете запускать любую услугу через это соединение.

По-прежнему могут возникать проблемы с подключением, но поскольку туннель будет более терпимым, любой сеанс ssh будет чувствовать короткое удержание, а не отсоединение.

Для этого вам понадобится VPN-сервис, который вы можете настроить на своем собственном сервере.

ответил hultqvist 28 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 28 Sep 2009 14:27:21 +0400 2009, 14:27:21
0

Поскольку autossh не отвечает нашим потребностям (он существует с ошибкой, если он не может подключиться к серверу с первой попытки), мы написали приложение pure bash: https://github.com/aktos-io/link-with-server

Он создает обратный туннель для sshd-порта NODE (22) на сервере по умолчанию. Если вам необходимо выполнить любые другие действия (например, пересылка дополнительных портов, отправка писем по подключению и т. Д.), Вы можете разместить свои сценарии on-connect и on-disconnect папки.

ответил ceremcem 15 J000000Saturday17 2017, 03:04:11

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132