Тримайте кілька тунелів 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Перепідключено має бути лише зупинений профіль, а інші сеанси повинні зберегти і процеси, і маршрути. Якщо перезапускаються два профілі, ваш ланцюг десь працює паралельно, де ви цього не очікували.
Чого сторож не повинен робити
Сторож, який перезапускає все за будь-якого збою, виглядає здоровим під час тестів і спричиняє збій у вікні обслуговування. Перезапускайте за профілем, ніколи глобально.
Надавайте перевагу підтримуваному клієнту, коли шлюз пропонує його для того самого протоколу, і ніколи не вписуйте пароль у скрипт і не передавайте його в командному рядку, бо файл профілю вже зберігає секрет. Якщо завдання має виконуватися від імені звичайного користувача після підняття тунелю, знижуйте привілеї зсередини скрипта, а не запускайте весь ланцюг під цим обліковим записом. Нарешті, перечитайте маршрути після перепідключення, бо профіль може повернутися з іншою призначеною адресою й залишити застарілий маршрут, якого жодна перевірка, спрямована на адресу тунелю, ніколи не помітить.