You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Мост снова поднимается сам после обрыва связи. До этой версии не поднимался - ни на платном тарифе, ни на бесплатном, и это та самая причина, по которой на него жаловались. Переподключение в клиенте есть с 0.6.3 и работает, когда обрыв видно. Обрыв в дороге не видно: ни FIN, ни RST ни до кого не доходят, сокет остаётся открытым, - и обе половины были устроены так, что верили молчанию. Клиент стучал, сервер не отвечал, поэтому канал был молчащим по построению, а мёртвый туннель ничем не отличался от простаивающего.
Ровно поэтому SSH переподключался всегда, а мост никогда. У SSH есть ServerAliveInterval. У моста был стук, на который никто не отвечал.
Что изменилось
Молчание стало приговором, а не состоянием. Сервер отвечает на каждый стук, и у клиента появился признак жизни, который не стоит ни одного байта данных. Молчание дольше 45 секунд (три пропущенных ответа) закрывает сеанс и передаёт дело уже существующему переподключению. Адрес при этом не меняется.
Сервер больше не блокирует сам себя при переподключении. Прощание с мёртвым сокетом держало единственный общий замок, а прощание с мёртвым сокетом длится столько, сколько ядро повторяет попытки, то есть минуты. Всё это время мост стоял целиком: посетитель не мог найти сеанс, соединение не принималось, новое рукопожатие не регистрировалось. Туннель не возвращался вообще. Теперь под замком только обмен записями в таблицах.
Живость проверяет и ядро. Keepalive на управляющем соединении со сроками 30/10/3 вместо двух часов по умолчанию, с обеих сторон: мёртвый канал замечается даже когда через туннель ничего не идёт.
Санация того, что остаётся после обрыва. Соединение, у которого своя программа не приняла сокет, закрывается сразу, а не висит у сервера в очереди, пока посетитель ждёт свой таймаут. Список обслуженных соединений в клиенте чистится - он не чистился никогда, и у долгоживущего туннеля рос с каждым запросом. Посетитель, которого не удалось передать клиенту, снимает сеанс, а не оставляет его глотать всех следующих.
Как пользоваться
В настройках, командах и флагах не изменилось ничего. Существующий профиль продолжает работать.
Два срока при необходимости правятся в src/tunnellio/bridge.py: HEARTBEAT_INTERVAL (15 с) и SILENCE_LIMIT (45 с). Предел должен оставаться не меньше трёх интервалов, иначе один потерянный пакет будет прочитан как обрыв.
Честное ограничение: между обрывом и тем, как клиент его заметит, проходит до 45 секунд. Посетители, пришедшие в это окно, получают 504 Gateway Timeout примерно через 15 секунд - это срок недоставленного соединения на сервере. Внятный отказ лучше страницы, которая грузится минуту, но это не нулевой простой, а сократить его можно только более частым стуком.
Changelog
Сервер моста отвечает на heartbeat. Раньше не мог: клиент стучит раз в 15 секунд, а ожидание чтения у сервера истекает через 30, поэтому свой heartbeat у сервера не наступал никогда и канал со стороны клиента был вечно молчащим.
Молчание дольше SILENCE_LIMIT (45 с) считается оборванным каналом: сеанс закрывается, дальше работает уже существующее переподключение с нарастающей паузой, под тем же именем.
На управляющем соединении включён TCP keepalive со сроками 30/10/3 - и в клиенте, и на сервере - вместо двух часов по умолчанию.
Сервер больше не прощается с прежним сеансом под общим замком. Прощание и ответы застрявшим посетителям уходят в фон со сроком, а сокет, не ответивший за этот срок, обрывается силой.
Посетитель, которого не удалось передать клиенту моста, снимает сеанс, а не оставляет его глотать каждого следующего.
Соединение, у которого своя программа не приняла сокет, закрывает свою сторону сразу, а не остаётся в очереди сервера.
Клиент чистит список потоков обслуженных соединений. Он не чистился никогда, и у долгоживущего туннеля рос с каждым запросом.
В ответе 503 застрявшему посетителю правильно указана длина тела: она была на байт меньше, и получатель дочитывал ответ до обрыва связи вместо аккуратного конца.
Снимок машины в мониторе моста снимается до замка, а не под ним.
Артефакты
tunnellio.exe - Windows x64, самостоятельный, Python не нужен
tunnellio-windows-x64-v0.6.5.zip - бинарник вместе с README, CHANGELOG, config.example.json и docs/
tunnellio-source-v0.6.5.zip - исходники из тега v0.6.5, без привязки к системе