Держите несколько туннелей vpnc с проверками для каждого профиля
Штатный скрипт переподключения рассчитан на один туннель. Дайте каждому профилю vpnc свой порт, проверяйте реальную службу и соедините проверки в одном фиксированном порядке.
Один профиль vpnc чисто переподключается после роуминга; три из них по очереди ломают друг другу сокеты, маршруты и состояние резолвера. Штатный скрипт переподключения написан для одного туннеля, поэтому перезапускает каждый профиль, как только любой из них недоступен. Чтобы это исправить, нужны три вещи: отдельные локальные порты, проверка, которая тестирует реальную службу для каждого профиля, и одна упорядоченная цепочка, которая никогда не запускает два подключения одновременно.
Дайте каждому профилю собственный локальный порт
Профиль vpnc, оставленный на локальном порте по умолчанию, конкурирует с уже работающим профилем. Второе подключение терпит неудачу, пока первое удерживает порт, и строка журнала выглядит как проблема шлюза, а не локальный конфликт. Вместо этого задайте по одной строке для каждого файла профиля:
Local Port 0Ноль позволяет ядру выбрать эфемерный порт, поэтому два профиля можно установить одновременно. Назовите каждый файл по шлюзу и группе, которой он служит, держите его читаемым только для root и всегда подключайтесь соответствующим профилем, а не общим по умолчанию. Общий файл по умолчанию — это способ, которым скрипт переподключает не тот туннель после того, как кто-то переименовал профиль.
Файлы профилей содержат учётные данные, поэтому права — часть проекта, а не уборки. Файл, читаемый всеми под /etc/vpnc, отдаёт групповой секрет каждому локальному пользователю. Держите режим 0600 с владельцем root и позвольте скриптам читать файл от имени root вместо копирования секретов в аргументы. Именно поэтому скрипт проверки никогда не должен выводить содержимое файла в журнал.
Проверяйте одну службу на профиль, а не адрес туннеля
Эхо-запрос на собственный адрес туннеля в основном доказывает, что интерфейс существует. Он ничего не говорит о том, достигает ли хост за ним приложения, которое оправдывает туннель. Интерфейс может быть поднят, пока маршрут за ним уже исчез.
Проверяйте одну службу на профиль с коротким тайм-аутом TCP и переподключайте только тот профиль, чья проверка не удалась. Две секунды отделяют мёртвый путь от медленного, а проверка TCP не зависит от того, разрешён ли ICMP где-либо по пути. Меняйте между профилями только цель и имя конфигурации:
#!/bin/bash
set -eu
if ! nc -z -w 2 10.63.7.20 8443; then
/usr/sbin/vpnc-connect ops.conf
fiСохраните это как /usr/local/bin/ensure-vpn-ops.sh, сделайте исполняемым и повторите для каждого профиля, меняя только цель проверки и имя конфигурации. Проверка, отвечающая на вопрос протокола, переживает шлюзы, которые отбрасывают эхо, но продолжают передавать службы, важные пользователям.
Соедините проверки в цепочку, чтобы они никогда не состязались
Штатный скрипт переподключения может вызывать ваши проверки по очереди, и очередь — это весь смысл. Два вызова vpnc-connect, работающие вместе, перезаписывают таблицу маршрутизации в порядке, который никто не контролирует, и именно так здоровый профиль теряет свой маршрут.
Держите вызовы на переднем плане, добавьте короткую задержку стабилизации для нижележащего интерфейса и планируйте цепочку из таблицы cron пользователя root, так как только root может перезаписывать маршруты туннеля:
#!/bin/bash
sleep 20
/usr/local/bin/ensure-vpn-ops.sh
/usr/local/bin/ensure-vpn-lab.shДержите порядок одинаковым между скриптом загрузки и записью cron, поскольку цепочка, которая при загрузке идёт в другом порядке, фактически является другой программой. Когда один профиль зависит от маршрутов другого, поставьте зависимость первой и позвольте более поздней проверке безвредно не удаться, пока предыдущий туннель ещё поднимается.
Следите за журналом, затем намеренно сломайте один
Записывайте по одной строке на запуск с профилем, целью проверки, результатом и предпринятым действием. Без этого туннель, который дёргается каждую минуту, выглядит точно так же, как тот, что никогда не падал, и ошибку проверки невозможно отличить от сбоя шлюза. Журнал также доказывает, что цепочка затронула только тот профиль, который не удался. Пишите его туда, где он переживёт перезагрузку, иначе доказательства уходят вместе с процессом.
Затем намеренно сломайте туннель и посмотрите, что произойдёт. Остановите один профиль и подтвердите, какие процессы и маршруты всё ещё присутствуют:
pgrep -a vpnc
ip -4 route show | grep -E '10[.]63|10[.]90'
tail -n 5 /var/log/ensure-vpn.logПереподключён должен быть только остановленный профиль, а остальные сеансы должны сохранить и процессы, и маршруты. Если перезапускаются два профиля, ваша цепочка где-то работает параллельно, где вы этого не ожидали.
Чего сторож не должен делать
Сторож, который перезапускает всё при любом сбое, выглядит здоровым во время тестов и вызывает сбой в окне обслуживания. Перезапускайте по профилю, никогда глобально.
Предпочитайте поддерживаемый клиент, когда шлюз предлагает его для того же протокола, и никогда не вписывайте пароль в скрипт и не передавайте его в командной строке, потому что файл профиля уже хранит секрет. Если задача должна выполняться от имени обычного пользователя после подъёма туннеля, снижайте привилегии изнутри скрипта, а не запускайте всю цепочку под этой учётной записью. Наконец, перечитайте маршруты после переподключения, потому что профиль может вернуться с другим назначенным адресом и оставить устаревший маршрут, которого никакая проверка, направленная на адрес туннеля, никогда не заметит.