Ping-сторож не отличает сломанный туннель от исправного
Пинг в интернет доказывает меньше, чем кажется. Проверяйте туннель изнутри, считайте сбои перед действием и считайте переключение сервера отдельным решением.
Три условия решают, помогает сторож или вредит: что способна различить проверка, сколько подряд идущих сбоев оправдывают действие и является ли действие переподключением или переключением. Строка cron, которая пингует публичный адрес, ни на одно из них не отвечает хорошо. Она переподключает исправные туннели и оставляет сломанные, и делает и то и другое без записи. Схема, которую стоит сохранить, делает эти три выбора явными.
Проверка — это часть, от которой зависит всё остальное.
Что на самом деле доказывает пинг в интернет
Пинг публичного резолвера показывает, что локальный путь в интернет жив. Он не доказывает, что туннель несёт трафик, а в профиле полного туннеля сам пинг идёт через туннель, так что исправный ответ и сломанный туннель могут существовать одновременно, пока клиент всё ещё передаёт пакеты. Если профиль отправляет поиск имён через туннель, сбой DNS читается как мёртвая связь и запускает переподключение, которое ничего не может исправить.
Ни одно из двух направлений ошибки не проявляется в коде возврата. Сторож, построенный на этом сигнале, — это бросок монеты с расписанием cron.
Проверяйте то, что живёт за туннелем
ip -brief addr show tun0 ip route get 10.100.20.10 nc -z -w3 10.100.20.10 443
Проверяйте изнутри, самая дешёвая проверка первой. Наличие интерфейса говорит, что туннель поднят; поиск маршрута к известному внутреннему адресу говорит, что трафик пойдёт туда; проверка TCP до хоста на другой стороне говорит, что что-то действительно отвечает. Одни только эхо-запросы вводят в заблуждение: многие внутренние хосты охотно отвечают по TCP, но отбрасывают ICMP, поэтому сторож на пинге постоянно переподключает туннель, который никогда не переставал работать.
Держите проверку ограниченной по времени и дайте ей отдельный код возврата. Проверка, которая висит тридцать секунд, превращает сторожа в детектор обрыва со встроенной задержкой.
Выберите между одной строкой и циклом
* * * * * nc -z -w5 10.100.20.10 443 || myvpn reconnect
Запись cron — это одна строка без памяти, что подходит ноутбуку, где лишнее переподключение ничего не стоит. Цикл под присмотром держит счётчик и действует только после нескольких промахов, что не даёт нестабильному каналу вызвать шквал переподключений. В любом случае запускайте его под супервизором, чтобы он пережил падение и писал в журнал. Выбирайте по тому, важно ли лишнее переподключение, а не по тому, какая версия короче.
failures=0 while sleep 30; do if nc -z -w5 10.100.20.10 443; then failures=0 else failures=$((failures+1)); fi if [ $failures -ge 3 ]; then myvpn reconnect; failures=0; fi done
Этот цикл считает подряд идущие сбои, а не долю за окно. Окну нужны часы и память образцов, и большинство ошибок в самодельных сторожах живёт именно в этой арифметике.
Переключение — это другое решение
Смена серверов отличается от переподключения. Сначала разорвите старое соединение, потому что второй клиент, запущенный, пока первый ещё держит адрес, столкнётся с ним. Считайте подряд идущие сбои перед сменой, ограничьте попытки и проверьте снова, когда новое соединение поднято, вместо того чтобы доверять коду возврата команды connect. Неверная конфигурация не должна кружить по всем серверам в цикле.
Не проверяйте собственный публичный адрес VPN-сервера изнутри полного туннеля. Эта проверка зависит от того, что она тестирует, и сообщает об успехе, когда пути, который она должна была подтвердить, уже нет.
Запишите, какая проверка выполнялась, что она вернула и какое действие последовало. Эта запись превращает загадочное переподключение в событие, которое можно диагностировать.