Запускайте задачи после VPN из диспетчера, а не из if-up
Старый хук интерфейса не увидит VPN-подключение. Сопоставляйте vpn-up с UUID профиля, делайте задачу повторяемой и планируйте отключение, которое никогда не сработает.
Скрипту, который должен выполняться после поднятия VPN, нужно событие от компонента, владеющего подключением. Файл, положенный в старый каталог сетевых хуков, не является обратным вызовом для каждого VPN, который могут создать NetworkManager, pppd или отдельный процесс OpenVPN. Каждый из этих владельцев сообщает о другом событии с другим окружением, поэтому владельца нужно определить до выбора хука. Иначе скрипт корректен и просто никогда не запускается.
Для VPN, управляемого NetworkManager, диспетчер — правильное место, а vpn-up — правильное действие.
Используйте vpn-up, а не событие интерфейса
Диспетчер различает up и vpn-up. Первый сообщает об активированном интерфейсе; второй сообщает об активированном VPN-подключении. Поднятие Wi-Fi означает лишь, что нижележащий канал существует; туннель может ещё договариваться или так и не аутентифицироваться.
Скрипт получает интерфейс и действие, а сведения о подключении приходят через окружение, включая UUID профиля и IP-интерфейс VPN. Читайте эти переменные, а не выводите идентичность из имён устройств.
Ограничьте совпадение одним подключением
Сопоставляйте по UUID подключения или по другой идентичности, которую передаёт диспетчер, а не по префиксу tun или ppp0. Имена интерфейсов нестабильны, одновременно может существовать больше одного туннеля, и два профиля могут носить одно и то же отображаемое имя. Сопоставление по префиксу tun означает, что скрипт рано или поздно сработает для подключения, которое никто не собирался трогать. Он также может сработать дважды для одного профиля, когда переподключение пересоздаёт устройство.
Сделайте задачу идемпотентной. Обратный вызов, добавляющий маршрут при каждом вызове, в конце концов заполняет таблицу дубликатами, и именно вторая копия ломает маршрутизацию.
Знайте, чего не доказывает активация
vpn-pre-up выполняется до того, как NetworkManager сообщит о полной активации VPN, и менеджер ждёт эти скрипты. Используйте блокирующую стадию только когда задача действительно принадлежит туда, потому что медленная проверка задерживает активацию, которую ждут все остальные компоненты.
Наличие маршрутов не доказывает, что приложение слушает, что частное имя разрешается или что существует пользовательская сессия. Проверяйте это отдельно с ограниченным тайм-аутом и сообщайте, какой уровень отказал, вместо повторения всей цепочки.
Уважайте контекст, в котором работает скрипт
Скрипты диспетчера работают от root, вне любой пользовательской сессии. Не предполагайте, что доступны окружение вошедшего пользователя, его графическая сессия или разблокированная связка ключей. Никто не должен отвечать на отсутствие контекста рабочего стола тем, чтобы сделать каждые учётные данные читаемыми для каждого процесса. Держите работу пользовательской сессии в пользовательской службе или помощнике сессии, которому обратный вызов может подать сигнал, не выдавая себя за пользователя.
Владение и права на скрипт тоже важны. Файл, исполняемый от root и заменяемый любым пользователем, — это путь к повышению привилегий, и это находка, независимая от того, верна ли логика VPN.
Планируйте отключение, которое никогда не сработает
NetworkManager документирует, что vpn-pre-down не выдаётся при принудительных отключениях, таких как неожиданное завершение или потеря связи. Поэтому очистка, построенная только вокруг мягкого pre-down, неполна по построению. Любое общее состояние, которое меняет скрипт, требует другого владельца, способного восстановить его после сбоя, и этот путь восстановления нужно проверять, а не предполагать.
Проверьте хук обычным подключением, переподключением, намеренным отключением и выдернутым кабелем. Записывайте UUID, действие и интерфейс, который сработал, не журналируя секреты. Эта запись — единственное надёжное доказательство того, что хук сработал для нужного вам подключения, и именно она делает следующее изменение безопасным.