Домашнему VPN нечего делать, когда ноутбук уже находится в этой сети. Заманчивый короткий путь — команда подготовки, которая завершается ненулевым кодом; это приводит к сбою unit и делает каждую панель похожей на сломанную. В systemd есть директива именно для такого решения, и она отделяет намеренный пропуск от настоящей неисправности. Сделать это правильно — в основном записать, что означает каждый код выхода.

Почему невыполненное предварительное условие — неправильная форма

ExecStartPre рассматривает ненулевой выход как сбой запуска, что правильно для команды, подготавливающей службу. Использование её в качестве условия делает политическое решение неотличимым от сломанной зависимости. ExecCondition существует, чтобы unit мог отказаться от запуска, не будучи помеченным как сбойный.

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

Сначала напишите контракт кодов выхода

Напишите контракт до скрипта. Выход с нулём означает продолжение, выход с единицей — пропуск оставшихся команд запуска, а выход с кодом 255 — что само условие не смогло выполниться. Коды от двух до 254 обычно тоже означают пропуск, о чём легко забыть, когда помощник возвращает случайный код ошибки. Drop-in ниже привязывает помощник к настоящему имени unit.

[Service]
ExecCondition=/usr/local/libexec/should-start-home-vpn

Проверьте действующий unit на унаследованные настройки SuccessExitStatus или stop-post, прежде чем предполагать семантику по умолчанию. Затем намеренно проверьте каждый из трёх исходов.

Сетевой признак не является доказательством местоположения

Доступный адрес маршрутизатора или известный MAC могут указывать на нужную сеть, и ни один из них этого не доказывает. Другая сеть может использовать тот же адрес, данные ARP могут быть устаревшими, а идентификаторы можно подделать. Относитесь к проверке как к оптимизации, согласованной с политикой, а не как к результату аутентификации.

Заранее решите, что означает неопределённость. Запуск VPN при неуверенности безопасен для клиента, который просто не смог бы подключиться; пропуск при неуверенности — нет. Сделайте проверку ограниченной и читайте активный интерфейс, а не предполагайте первый в списке. Проверка, которая зависает, хуже той, что отвечает «нет», потому что unit её ждёт.

Запишите эти допущения рядом с файлом unit, чтобы следующий человек знал, во что верит помощник. Комментарий в начале скрипта — самое дешёвое место, чтобы их хранить.

Обработайте переключение между сетями

Условие выполняется при запуске службы и позже не переоценивается. Пропущенный unit остаётся пропущенным после того, как ноутбук переедет в кафе, а работающий туннель остаётся поднятым после того, как ноутбук вернётся домой. Свяжите жизненный цикл смены сети с решением о запуске и остановке через отдельный механизм.

systemctl cat home-vpn.service

Проверьте четыре случая: запуск дома, запуск вне дома, проверку, которая не может выполниться, и переключение между сетями, пока unit активен. Держите причину пропуска видимой в журнале, чтобы намеренное решение никогда не выглядело как сбой аутентификации. Справочник службы описывает семантику выхода и минимальную версию.

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