Автоматизируйте вход в VPN, когда у клиента нет API или CLI
Выберите путь скрипта по тому, что предоставляет клиент: профиль, принадлежащий операционной системе, CLI поставщика, читающий секрет из stdin, или автоматизация GUI как последнее средство.
Это решают три вопроса, и только три. Создаёт ли клиент в операционной системе запись подключения, которая переживает перезагрузку? Предоставляет ли он командную строку, способную взять секрет не из своего списка аргументов? Заставляет ли требование идентичности человека отвечать на запрос в браузере? Ответьте в этом порядке, и выбор перестаёт быть делом вкуса, потому что запланированная задача может быть безголовой лишь настолько, насколько позволяет самый слабый из трёх ответов.
Сопоставьте клиента с тремя скриптуемыми уровнями
Собственный профиль ОС, CLI поставщика, клиент только с GUI и клиент с браузерным SSO требуют четырёх разных подходов. Первые два переживают перезагрузки без присмотра, и перезагрузка без присмотра в этом весь смысл. Остальным двум нужно проектное решение раньше, чем скрипт.
| What the client exposes | What to script | What still bites |
|---|---|---|
| OS-native connection entry | rasdial, scutil --nc, nmcli | Tunnel is up before DNS and routes settle |
| Vendor CLI reading stdin | CLI wrapped by the scheduler, secret from the credential store | Prompt text changes between releases |
| GUI only | Pinned version plus a state assertion | Locale and DPI break the click targets |
Путь первый: профилем уже владеет операционная система
Это самый дешёвый путь и тот, который большинство упускает. В Windows rasdial "Office" подключается, а rasdial "Office" /disconnect закрывает соединение; rasphone -d "Office" управляет той же записью через интерфейс коммутируемого доступа. macOS перечисляет сохранённые службы с помощью scutil --nc list и запускает одну с помощью scutil --nc start. Linux передаёт работу NetworkManager.
rasdial "Office" user *
scutil --nc start "Office"
nmcli connection up id Office
nmcli -t -f GENERAL.STATE connection show OfficeЭти интерфейсы знают только профили, принадлежащие ОС, поэтому не могут управлять произвольным сторонним клиентом. Если профиля нет, создайте его один раз и дайте скрипту проверять его, а не создавать заново при каждом запуске. Сделайте скрипт идемпотентным: прочитайте текущее состояние, подключайтесь только при разрыве, а затем проверьте частное имя, которое задаче действительно нужно.
Путь второй: поставщик поставляет командную строку
Некоторые клиенты раскрывают достаточно командной строки, чтобы их можно было обернуть: у Cisco AnyConnect годами есть помощник только для подключения, а OpenConnect говорит на протоколах AnyConnect, GlobalProtect и Pulse из одного бинарного файла. Важное требование не список флагов, а то, откуда берётся секрет, потому что пароль в списке аргументов может прочитать любой, кто умеет перечислять процессы.
printf '%s\n' "$VPN_PASS" | openconnect --protocol=anyconnect \
--user "$VPN_USER" --passwd-on-stdin vpn.example.comУ FortiClient и некоторых сборок GlobalProtect вообще нет поддерживаемого CLI, а общественный клиент или замена с лицензией поставщика это решение о закупке, а не обход. В CI дайте служебной учётной записи права именно на этот бинарный файл, а не на оболочку, чтобы внедрённый аргумент не мог стать командой root.
Путь третий: автоматизация GUI и почему она последняя
Когда у официального клиента нет интерфейса, скрипты нажимают кнопки через оконные сообщения или SendKeys. Это хрупко по отношению к версии и языку, может оставить полуподключённый сеанс и тихо отказывает, когда диалог появляется не на том языке. Если выбираете этот путь, закрепите версию клиента, затем проверьте получившееся состояние соединения и держите документированный ручной запасной план рядом со скриптом.
Та же осторожность относится к принудительному отключению клиента убийством его процесса. Туннель может пережить процесс, или супервизор может перезапустить его, поэтому убить-и-перезапустить тоже не надёжный сброс.
Что ломается после подъёма туннеля
Успешное подключение доказывает аутентификацию и ничего больше. Проверьте ресурс, ради которого существует задача, его собственным протоколом и коротким тайм-аутом, и назовите этап в сообщении об ошибке. Профили, сертификаты и сохранённые учётные данные, видимые на вашем рабочем столе, могут быть невидимы для сеанса службы, поэтому запустите задачу один раз под собственной учётной записью планировщика, прежде чем ей доверять.
Ограничьте повторы. Цикл, повторяющий отклонённые учётные данные, блокирует учётные записи, а на запрос MFA безголовая задача не может ответить без проекта регистрации; скриптовые повторы против потока браузерного SSO просто сжигают попытки. Предпочитайте полезную нагрузку VPN, доставляемую через MDM, или профиль конфигурации для парка, где платформа владеет жизненным циклом учётных данных, и держите скрипты для клиентов, которыми так управлять нельзя.
Записывайте код выхода и первый сбойный ресурс, а не сам факт запуска скрипта. Именно эта строка превращает предупреждение планировщика в диагностику за пять минут.