Три условия решают, помогает сторож или вредит: что способна различить проверка, сколько подряд идущих сбоев оправдывают действие и является ли действие переподключением или переключением. Строка 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-сервера изнутри полного туннеля. Эта проверка зависит от того, что она тестирует, и сообщает об успехе, когда пути, который она должна была подтвердить, уже нет.

Запишите, какая проверка выполнялась, что она вернула и какое действие последовало. Эта запись превращает загадочное переподключение в событие, которое можно диагностировать.

Похожие статьи