Последующие действия: похоже, что быстрые серии отключений, совпадающие с несколькими месяцами работы каждого сервера, вероятно, случайны и служат только для выявления реальной проблемы. Причина, по которой ему не удалось восстановить соединение, почти наверняка связана со значениями AliveInterval (ответ Касперда). Использование параметра ExitOnForwardFailure должно позволить истечь тайм-аут перед повторным подключением, что должно решить проблему в большинстве случаев. Предложение MadHatter (сценарий уничтожения), вероятно, является лучшим способом убедиться, что туннель может повторно подключиться, даже если все остальное терпит неудачу.
У меня есть сервер (A) за брандмауэром, который инициирует обратный туннель на нескольких портах к небольшому VPS (B) DigitalOcean, чтобы я мог подключиться к A через IP-адрес B. Туннель непрерывно работал в течение примерно 3 месяцев, но неожиданно четыре раза за последние 24 часа произошел сбой. То же самое произошло некоторое время назад с другим провайдером VPS - месяцы безупречной работы, а затем внезапные множественные быстрые сбои.
У меня есть сценарий на компьютере A, который автоматически выполняет команду туннеля ( ssh -R *:X:localhost:X address_of_B
для каждого порта X), но когда он выполняется, он говорит Warning: remote port forwarding failed for listen port X
.
Зайдя в sshd /var/log/secure
на сервере, вы увидите следующие ошибки:
bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X
Решение требует перезагрузки VPS. До этого все попытки переподключения дают сообщение «Переадресация удаленного порта» и не будут работать. Теперь дело доходит до того, что туннель длится всего около 4 часов до остановки.
На VPS ничего не изменилось, и это одноразовый однопользовательский компьютер, который служит только конечной точкой обратного туннеля. Это работает OpenSSH_5.3p1 на CentOS 6.5. Кажется, что sshd не закрывает порты на своем конце, когда соединение потеряно. Я затрудняюсь объяснить, почему или почему это внезапно произойдет сейчас после месяцев почти идеальной работы.
Чтобы уточнить, мне сначала нужно выяснить, почему sshd отказывается прослушивать порты после сбоя туннеля, что, по-видимому, вызвано тем, что sshd оставляет порты открытыми и никогда не закрывает их. Это, кажется, главная проблема. Я просто не уверен, что заставило бы его вести себя таким образом после нескольких месяцев поведения, как я ожидаю (то есть закрытие портов сразу и повторное подключение скрипта).
источник
Ответы:
Я согласен с MadHatter, что это может быть переадресация портов из несуществующих соединений ssh. Даже если ваша текущая проблема окажется чем-то другим, вы можете рано или поздно столкнуться с такими несуществующими ssh-соединениями.
Существует три способа, по которым такие несуществующие соединения могут происходить:
Выяснение того, что из вышеперечисленных событий происходит, не очень важно, потому что есть метод, который решит все три проблемы. Это использование сообщений keepalive.
Вы должны посмотреть на
ClientAliveInterval
ключевое слово дляsshd_config
иServerAliveInterval
интервал дляssh_config
или~/.ssh/config
.Выполнение
ssh
команды в цикле может работать нормально. Хорошей идеей будет также включить спящий режим в цикл, чтобы не вызывать переполнение сервера при сбое соединения по какой-либо причине.Если клиент переподключится до того, как соединение будет разорвано на сервере, вы можете оказаться в ситуации, когда новое ssh-соединение работает, но не имеет переадресаций портов. Чтобы избежать этого, вам нужно использовать
ExitOnForwardFailure
ключевое слово на стороне клиента.источник
-o ExitOnForwardFailure yes
это именно то, что мне было нужно. Так что это еще одна вещь, которую мне нужно выяснить. Чтобы подумать, я собирался написать скрипт Python для разбора этих предупреждающих сообщений. Это намного проще. : DExitOnForwardFailure
написании моего ответа. Я добавил это к ответу сейчас.-o ExitOnForwardFailure=yes
(обратите внимание на знак равенства). Поэтому, если кто-то сталкивается с этим, не копируйте и не вставляйте из моего предыдущего комментария, это не сработает. : PВы можете найти процесс, который связывает порт на этом сервере с
Скорее всего, это полусуществующее
sshd
, но зачем делать предположения, когда вы можете иметь данные? Это также хороший способ для сценария найти PID для отправки сигнала 9, прежде чем пытаться снова запустить туннель.источник
Для меня, когда
ssh
туннель отключается, требуется некоторое время для сброса соединения, поэтомуssh
процесс продолжает блокироваться, оставляя меня без активных туннелей, и я не знаю почему. Обходное решение состоит в том, чтобы перевестиssh
в фоновый режим-f
и порождать новые соединения, не дожидаясь сброса старых соединений.-o ExitOnForwardFailure=yes
Может быть использованы для Нта количества новых процессов.-o ServerAliveInterval=60
Повышает надежность вашего текущего соединения.Вы можете
ssh
часто повторять команду, скажем, вcron
или в цикле в вашем скрипте, например, в следующем, мы запускаемssh
команду каждые 3 минуты:источник
-o ExitOnForwardFailure=yes
было то, что я искал, спасибо большое!По моему опыту ssh имеет немного утомительную привычку не выходить чисто, если «что-то» все еще работает в удаленной системе. Например, началось в фоновом режиме. Вы можете воспроизвести это:
Ваш ssh выйдет из системы, но на самом деле не закроет сеанс - пока не завершится удаленный процесс (чего не произойдет, потому что это цикл «while true»). Может случиться что-то похожее - ваш сеанс имеет «застрявший» процесс, который порождается ssh. Порт остается в использовании, и поэтому он не может быть повторно использован вашим локальным процессом.
источник
ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &
так что SSH не выполняет ничего, кроме самого туннеля, в частности, из-за опции -N. Все, что остается открытым, выполняется на удаленном сервере B с использованием самого sshd.