Юниты могут выглядеть правильно, systemctl start может сообщать об успехе, а через десять секунд служба стоит неактивной. Или она перезапускается каждые полминуты, пока её не остановит предел запусков. Ни одно из поведений не является сетевым сбоем: юнит описывает время жизни процесса, которое не соответствует тому, что клиент делает на самом деле. Клиент может ответвиться и выйти или настроить сеанс и сразу выйти.

Почему юнит становится неактивным через секунды после успешного запуска

systemd выводит состояние из процесса, который сам запустил, поэтому Type= — утверждение об этом процессе, а не документация. С Type=simple юнит считается активным, пока команда работает, и становится неактивным, когда она возвращается. Клиент, который передаёт соединение вспомогательной программе и выходит, поэтому выглядит как авария, даже когда туннель поднят. Тогда журнал показывает схему запуска и остановки, которая читается как сбойный бинарник.

Прочитайте тип юнита рядом с поведением клиента, прежде чем трогать сетевую конфигурацию.

Выберите тип, который соответствует клиенту

Две схемы охватывают большинство CLI поставщиков: команда, которая настраивает сеанс и выходит, и команда, которая перед возвратом ответвляет вспомогательную программу. Каждая требует своей формы юнита.

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/protonvpn-cli connect -f
ExecStop=/usr/bin/protonvpn-cli disconnect

oneshot вместе с RemainAfterExit=true оставляет юнит активным после возврата команды, что соответствует схеме настрой и выйди, а команда остановки даёт службе чистое завершение. Ответвляющийся клиент сохраняет ту же форму, но ему нужен Type=forking, чтобы systemd следил за дочерним процессом. Задайте Restart=on-failure, RestartSec=30 и конечный StartLimitBurst, чтобы сбой поставщика не превратился в цикл перезапусков, который прячет ошибку.

Никогда не позволяйте управляемому клиенту демонизироваться

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

Процесс, который отделяется от самого себя, невидим для всего, что должно было за ним следить.

Сеанс заканчивается и уносит туннель с собой

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

Пользователь службы — это вторая половина той же проблемы. Ключ, принадлежащий root с режимом 0600, нечитаем для юнита, работающего под другой учётной записью, что бы sudo ни достиг в вашей оболочке.

systemctl cat openvpn-server@work
sudo chown -R openvpn:network /etc/openvpn/server
sudo find /etc/openvpn -type f -perm /077 -ls

Упорядочьте зависимые службы после появления адреса

Когда демон привязывается к адресу туннеля, который ещё не создан, он выходит с сообщением Cannot assign requested address. Исправление — явное упорядочивание, а не цикл повторных попыток.

[Unit]
After=network.target [email protected]
Requires=sys-devices-virtual-net-wg0.device

After= упорядочивает задачи, а Requires= на юните устройства привязывает зависимую службу к существованию интерфейса, что сильнее, чем ждать только сетевую цель. Перезагрузите менеджер после правки и перезапустите зависимую службу, а затем прочитайте её журнал вместо того, чтобы считать, что порядок сработал. Направляйте вывод клиента в журнал через StandardOutput=journal или параметр логирования, потому что управляемый клиент, пишущий в файл, который никто не открывает, выглядит точно так же, как тот, что так и не запустился.

Затем один раз перезагрузитесь и убедитесь, что юнит активен после появления устройства туннеля. Исправление, проверенное только через systemctl start, не проверило порядок загрузки, который должен был исправить.

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