Как можно снова "сбросить", но все еще подключенный туннель обратного SSH?
У меня есть удаленный компьютер Raspberry Pi, который подключается из-за ограничительного брандмауэра к моему серверу через обратный туннель SSH. Представьте, что этот Raspberry Pi находится на труднодоступной крыше здания в другой стране (возможно, во время шторма), поэтому я хочу, чтобы его подключение было надежным.
Чтобы подключиться к серверу, Raspberry Pi запускает такой процесс:
while true; do
ssh -R 19999:localhost:22 www.sern.pro
sleep 30
done
Часть 19999:localhost:22
в основном это означает, что весь трафик через порт 19999 на сервере должен быть перенаправлен на порт 22 Raspberry Pi. Итак, я могу подключиться к Raspberry Pi по SSHing к серверу, а затем выполнить команду, подобную следующей:
ssh localhost -p 19999
Это обычно работает просто отлично, и на сервере, команда как netstat --all --timers --program --numeric | egrep '127.0.0.1:*(LISTEN|.*)' | sort
перечисляет обратное соединение SSH как-то так:
tcp 0 0 127.0.0.1:19999 0.0.0.0:* LISTEN 2972/5 off (0.00/0/0)
Однако иногда я обнаруживал, что этот список на сервере исчезает, пока Raspberry Pi поддерживает SSH-соединение с сервером. То есть команда ssh localhost -p 19999
в результате появляется сообщение об ошибке, подобное следующему:
ssh: connect to host localhost port 19999: Connection refused
Тем не менее, соединение Raspberry Pi SSH остается идеальным, способным выполнять команды на сервере. Я не знаю правильных слов, чтобы описать, что происходит не так, когда это происходит.
Итак... если не считать бронирование рейса и восхождение на крышу здания, как я могу снова подобрать это активное соединение SSH как правильный обратный туннель SSH? Как я могу снова получить доступ к локальному порту?
2 ответа
Более десяти лет назад autossh
Утилита была написана для таких целей.
Вы можете использовать следующий скрипт подключения
#!/bin/sh
export AUTOSSH_GATETIME=0
autossh -M 0
-o "PubkeyAuthentication=yes" \
-o "StrictHostKeyChecking=false" \
-o "PasswordAuthentication=no" \
-o "ExitOnForwardFailure=yes" \
-o "ServerAliveInterval 60" \
-o "ServerAliveCountMax 3" \
-fNR 19999:localhost:22 www.sern.pro
Конечно, вам нужно установить аутентификацию на основе ключей перед запуском этого скрипта.
Проблема, с которой вы сталкиваетесь, означает, что соединение недоступно. Если в конце команды вы увидите список всех соединений, вы, возможно, увидите, что соединение с этим портом больше не находится в режиме LISTEN и теперь оно является TIME-WAIT или ЗАКРЫТЬ-ПОДОЖДИТЕ, это означает, что соединения все еще "живы", но только как запущенный процесс в малине.
Чтобы это работало, вы можете создать скрипт, который проверяет наличие обратного соединения, если не настроил его.
Чтобы решить эту проблему, вы можете добавить код в скрипт, чтобы проверить, есть ли на модуле идентификатор процесса ssh, и если у вас есть файл маркера, вы убьете этот процесс, чтобы перезапустить туннель снова.
Например, у вас есть пустой файл с именем RESTARTSSH, в своем скрипте вы можете проверить, существует ли этот файл, если да, то найдите идентификатор процесса ssh и уничтожьте его, а затем перезапустите туннель.
Для проверки идентификатора процесса вы можете использовать:
ps -ef | grep ServerAliveInterval | grep -v grep | awk '{print $2}'