Прив'язка залежної служби до tun0.device виглядає як підписка на тунель, але це не так. Юніт пристрою відображає існування інтерфейсу, і це може залишатися істинним під час невдалого з'єднання та наступного перепідключення. Тоді служба діє не того моменту або не діє взагалі, залежно від того, чи зникав інтерфейс між ними. Хук, що описує подію, яка вам справді важлива, — це той, який викликає OpenVPN, а не той, який виводить systemd.

Вирішіть, яка умова потрібна службі, перш ніж вибирати тригер, бо три кандидати не взаємозамінні.

Що насправді відстежує юніт пристрою

systemd створює юніт пристрою з погляду ядра на мережевий інтерфейс, тому tun0.device стає активним, коли інтерфейс з'являється, і неактивним, коли його видаляють. З persist-tun м'який перезапуск зберігає інтерфейс на місці, тож юніт ніколи не блимає і нічого прив'язаного до нього не запускається. Навіть без збереження стану юніт нічого не каже про маршрути, DNS або про те, чи відповідає віддалена сторона.

Це робить його поганим замінником «VPN готовий». Слухачеві, якому потрібна лише локальна адреса, може вистачити існування інтерфейсу, тоді як службі, що викликає застосунок у віддаленій мережі, потрібні маршрути й доступність, чого юніт пристрою не може виразити.

up, route-up і up-restart означають різні речі

up виконується після відкриття пристрою TUN/TAP і налаштування інтерфейсу — це правильний момент для слухача, який прив'язує призначену адресу. route-up виконується після встановлення маршрутів, з урахуванням будь-якої налаштованої затримки маршруту, і підходить для роботи, що потребує завершеного етапу маршрутів. Жоден не доводить, що віддалений застосунок відповідає. Вибір між ними — питання про те, що потрібно службі, а не про те, який хук звучить завершеніше.

З persist-tun перезапуски повторно використовують пристрій, тому up не виконується знову, якщо не задано up-restart. Ця опція вмикає up-скрипт для задокументованого життєвого циклу перезапуску, а його середовище урізане порівняно з першим запуском. Скрипт, який припускає повне середовище, працює при першому з'єднанні й падає при наступному.

Надішліть дію, не чекаючи на неї

Хук, що синхронно викликає systemctl restart, може зайти в глухий кут із юнітом, порядок якого чекає на тунель. systemctl --no-block try-restart vpn-dependent.service ставить завдання в чергу й повертається, що не дає хуку заблокувати з'єднання, на яке він реагував. try-restart діє лише на запущений юніт, тоді як restart запускає й неактивний; вибирайте свідомо, а не за звичкою.

Постановка в чергу — не перевірка. Хук повертає успіх, щойно завдання прийнято, тому перевірка має відбуватися в журналі цільового юніта або в його фактичному стані слухача.

Політика перезапуску живе в юніті, а не в хуку

Юніт oneshot із RemainAfterExit=yes залишається активним після завершення команди, а другий запит на запуск нічого не робить, бо systemd вважає його вже запущеним. Це властивість, навколо якої проєктують, а не дефект, який обходять повторними викликами запуску. Якщо дія має виконуватися на кожне з'єднання, юніту потрібна форма, яка це дозволяє.

After= упорядковує юніти, а BindsTo= зв'язує часи життя, але жодне не означає «перезапускай це щоразу, коли VPN перепідключається». Юніт, прив'язаний до тунелю, зупиняється, коли зупиняється тунель; він не перезапускає себе, коли тунель повертається, якщо щось не запустить його знову.

Перевірте три перепідключення, а не одне

Холодне завантаження, повний перезапуск клієнта й м'яке перепідключення відпрацьовують кожен свій шлях. М'яке перепідключення — це те, що виявляє відсутній up-restart, урізане середовище або юніт пристрою, який так і не став неактивним. Запустіть усі три й підтвердьте обидва напрямки: служба діє, коли тунель піднімається, і не перезапускається при не пов'язаних змінах каналу, як-от роумінг Wi-Fi.

Зберігайте незалежний шлях відновлення, якщо залежна служба несе ваш власний адміністративний доступ. Хук, що перезапускає те, через що ви підключені, — це зміна, яка може замкнути вас ззовні.

Схожі статті