Какие существуют адекватные способы предотвратить сбрасывание SSH тунелей?
Привет, Хабровчане. Пишу тут в надежде услышать действительно опытных людей в системном администрировании.
Ситуация следующая - у нас есть множество клиентских пк, почти все из них за NAT-ами. Для обхода этого используется классическая схема с удалённым пробросом поротов через "белый" сервер, после чего эти порты вспомогательными скриптами пишутся в скульную базу, привязываясь локальными неймингами для дальнейших телодвижений. Но суть не в этом. Всё работает безукоризненно, но мне никак не победить "отвал" туннелей.
Из того, что мне удалось выяснить - если по тунелю не идёт некое (допопдле неизвестно, какое) время сигнал, то это соединение становится "повисшим", но при этом всём, активным. Я действительно столкнулся с этим и продолжаю сталкиваться повсеместно. Я пытался вывести хотя бы приблизительную закономерность по аптаймам туннелей, скорости интернета у клиента и т.д, но её НЕ существует (боже, я правда делал это долго).
И нет, меня не забанили в гугле, но проблема в том, что под винду нет каких-то очевидных способов бороться с этм (как, autossh в linux, например)... Ну либо я их не нашёл
Клиентские устройства работают под виндой, для проброса я использую plink, который, как выяснилось, не имеет такого параметра, как KeepAlive в принципе, в отличии от того же PuTTY. На задворках старых форумах мне попалась некая утилита, как MyEnTunnel. Она оперирует всё тем же плинком, но помимо необходимого нам порта может пробрасывать т.н. контрольный порт, по которому она гоняет пакеты (loopback pinging). Но тут вырисовывается проблемы - портов становится n*2, что для меня абсолютно неприемлемо, а вторая чуть более тривиальна - я абсолютно не понимаю, каким образом гоняя пакеты по другому порту, она спасёт наш от "отвисания".
По итогу я в отчаянии и вижу лишь два варианта, и все они с колоссальными компромиссами - первый, это костылями грузить в plink сохранённые профили, которые хранятся в реестре, перезаписывая КАЖДЫЙ раз актуальные данные для проброса в этот самый реестр (в них можно сохранить все настройки, в т.ч. и KeepAlive), в надежде, что это мне вообще поможет.
Либо сбрасывать соединение каждые +- полчаса и создавать новое, тем самым DDOS-я сервер и предусматривать возможность того, что будет сброшено действительно активное подключение, что тоже не подходит от слова совсем
Понимаю, много слов и сумбур, но надеюсь, что знающие люди поняли суть проблемы и прояснят мне доступные пути решения
Я знаю про OpenSSH под винду, это, вероятно, был бы крайним способом. Ибо выбрал я putty & co именно из-за их портабельности и переносимости. Клиентские устройства - это винды всех сортов и размеров (win 7 32 home, до win 10 ltsc) и даже представлять не хочется, сколько нюансов у меня возникнет, если я пойду в этом направлении.
А насчёт скрипта - я видел этот вариант, разумеется, но туннелей будет действительно много и как это повлияет на сервер. Тем более, если не самое главное - прокидывается порт не для классического применения SSH (если быть конкретным - два локальных порта под VNC и еще один под скрипт, слушающий сокет на Пайтон скрипте) и что-то мне подсказывает, что такая отправка пакетов в одну сторону не лучшее решение
fcgm, скрипт не создаст ощутимых проблем, так как запускается на клиентах. Другое дело, что у меня нет под рукой прямо сейчас схожей инфраструктуры чтобы проверить как это будет работать на винде.
Конечно, я ещё мог бы сказать, что использование ssh-туннелей не самый удобный метод, по сравнению, например, с openvpn/softher и прочим решениям для туннелирования
Я понимаю, что ssh это действительно не лучший выбор для такого, но были причины пойти именно в этом направлении, сейчас же - всё построено на этом и назад дороги уже нет)
Я попробую портировать под винду вариант, описанный в этом ответе, благодарю
Не очень понял, как все это у вас работает, но вариант навскидку - создавать при поднятии ssh-соединения с помощью plink также фейковый порт-форвардинг через соответствующий параметр командной строки и каким-либо образом периодически пытаться его задействовать, хотя бы простейшей вызываемой из шедулера командой вроде echo | telnet localhost PORT
Это именно то, что делает MyEnTunnel, как я понимаю, так? Не могли бы вы мне объяснить, как это работает и, главное, как спасает от "отвисания" основной порт. Я сам далеко не сис. админ, скорее программист. Но реальность такова, что пришлось столкнуться с такими тонкостями работы этого протокола
О том, что и как у меня работает - ответил вкратце Дмитрию Шицкоу
fcgm, от зависания чего-либо внутри самого ssh-соединения это конечно не спасет, но спасет от закрытия TCP-соединения по таймауту из-за отсутствия какого-либо трафика в нем, а также от "протухания" записи об этом соединении в таблицах маршрутизаторов, выполняющих NAT. Но вообще конечно лучше всю эту конструкцию реализовать более подходящими и удобными инструментами.
kepalive windows, а для автоматизации посмотреть параметры сессии.
Да и скорее всего это можно прописать в конфиге putty это же просто порт с линукса,
P.s.
На работе win8, putty не отваливается по таймауту так что скорее всего nat режет tcp по тайм-ауту, обойти можно просто одним пингом раз в 30 сек, возможно придётся увеличить размер пакета пинга чтобы tcp посчитало его пакетом данных
Я прописал исполнять удалённую команду while sleep 0.5; do echo -n .; done
Также сам plink крутится в вечном цикле: for /l %%i in () do plink -batch "SomeVPS Tunnel"
MyEnTunnel у меня стабильно отваливалась через несколько часов и переподключалась только вручную.
Вот код python, который еще ни разу не сбоил:
import datetime
import time
from sshtunnel import SSHTunnelForwarder
server = SSHTunnelForwarder(
('host', 1024),
ssh_username="host11111",
ssh_password="xxxxx",
remote_bind_address=('127.0.0.1', 3306),
local_bind_address=('127.0.0.1', 3306)
)
while True:
if not server.is_active:
print(f'{datetime.datetime.now()} server restart')
server.stop()
server.start()
time.sleep(15)