У вас есть сохранённая служба VPN в Системных настройках, и вы хотите, чтобы терминал её запустил. В macOS поддерживаемый путь — scutil --nc, но только для служб, которыми владеет собственный менеджер сетевых подключений системы. Строка меню — не API: у сторонних клиентов обычно есть собственная автоматизация, а профиль, отправленный службой управления, может отказать в локальном запуске. Это мой контрольный список: найти точную службу, прочитать её состояние, запустить её, дождаться изменения состояния и затем доказать, что трафик действительно идёт через туннель. Остановитесь на первом шаге, который не сходится, потому что каждая следующая команда предполагает, что предыдущая удалась.

Найдите службу, прежде чем пытаться её запустить

Начните с инвентаризации, а не с имени профиля, которое помните:

scutil --nc help
scutil --nc list

Каждая строка сопоставляет состояние с идентификатором службы, типом и отображаемым именем. Идентификатор — это значение, по которому пишут скрипты, потому что отображаемые имена повторяются и могут быть изменены. Руководство scutil от Apple документирует режим сетевого подключения, а установленный --nc help — авторитетный список подкоманд на этом Mac; не предполагайте, что флаг из старого руководства всё ещё существует в вашей версии macOS.

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

Прочитайте текущее состояние и подтвердите селектор

Спросите состояние службы перед запуском, чтобы знать, что должен изменить успешный запуск:

scutil --nc status "Office VPN"

Если две службы делят отображаемое имя, имя неоднозначно. Передайте вместо него идентификатор; команда принимает и то и другое, но только идентификатор гарантирует выбор одной службы. Проверьте, что слово состояния вам знакомо, — обычно Connected, Disconnected, Connecting или Disconnecting, — прежде чем разбирать его в скрипте. Проверьте также, управляется ли профиль, потому что заблокированная конфигурация может принять команду и всё равно проигнорировать её или запросить подтверждение.

Этот запрос состояния дёшев, поэтому используйте его как страж в автоматизации: запускайте только когда состояние Disconnected, и не считайте Connecting ошибкой. Если служба уже Connected, пропустите запуск, а не прерывайте работающий туннель.

Запустите подключение и дождитесь стабилизации состояния

Запрос на запуск асинхронен. Команда возвращается, когда запрос принят, а не когда завершилась аутентификация или установлены маршруты. Запустите её, затем опрашивайте состояние с ограниченным ожиданием и выходите, если служба возвращается в Disconnected:

scutil --nc start "Office VPN"
n=0
while [ "$n" -lt 30 ]; do
  state=$(scutil --nc status "Office VPN" | head -n 1)
  [ "$state" = "Connected" ] && break
  [ "$state" = "Disconnected" ] && { echo "start failed"; exit 1; }
  sleep 2
  n=$((n + 1))
done

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

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

Докажите, что туннель несёт трафик, а не просто говорит Connected

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

ifconfig -l
netstat -rn -f inet
netstat -rn -f inet6
scutil --dns

Найдите интерфейс, созданный службой, вместо того чтобы угадывать номер, затем спросите таблицу маршрутизации, какой интерфейс использует конкретное назначение: route -n get 10.0.0.10, подставив внутренний хост. Если она сообщает физический интерфейс, туннель включён, но не несёт этот поток. Проверьте маршруты раздельного туннеля, порядок резолверов и любое локальное правило межсетевого экрана, которое разрешает интерфейс туннеля, но не процесс.

Разрешение имён — обычный ложный отрицательный результат. Внутренние имена могут разрешаться через неверный резолвер, пока туннель полностью здоров, что выглядит как сбой VPN и им не является. scutil --dns показывает порядок, который будет использовать macOS; после смены резолвера очистите кэш с помощью dscacheutil -flushcache и sudo killall -HUP mDNSResponder.

Держите учётные данные и привилегии вне командной строки

Никогда не помещайте пароль, предварительно общий ключ или токен в аргументы. Аргументы видны в списках процессов и попадают в историю оболочки, а скопированная запись поддержки может их раскрыть. Собственная обработка учётных данных профиля — будь то элемент Keychain, системный запрос или поток аутентификации клиента — это место для секретов.

Запуск команды с sudo не делает интерактивный вход необслуживаемым. Он меняет действующего пользователя, а не доступность запроса GUI, аппаратного токена или связки ключей входа. LaunchAgent может запустить службу после того, как пользователь вошёл и связка ключей разблокирована; LaunchDaemon обычно не достигает этих частей пользовательской сессии. Если организация управляет службой, её правила жизненного цикла главнее любого локального скрипта.

Остановите службу и проверьте, что она осталась остановленной

Остановите тем же селектором, который использовали для запуска, затем прочитайте состояние снова вместо того, чтобы предполагать, что туннель исчез:

scutil --nc stop "Office VPN"
scutil --nc status "Office VPN"

Остановка, возвращающаяся в Disconnected, всё же оставляет одну вещь для проверки: настроен ли профиль на подключение по требованию, что может вернуть его без вашего скрипта. Если другой клиент владеет маршрутами на том же Mac, эти маршруты могут пережить собственную остановку. Повторно проверьте маршрут, прежде чем заключить, что машина вне VPN.

Для вручную запускаемой обёртки держите порядок фиксированным: список, состояние, запуск, опрос, проверка маршрута, остановка, подтверждение. Не разбирайте дружественное имя из свободного вывода, когда идентификатор доступен, и не считайте выход команды запуска готовностью. Менеджер подключений сообщает состояние; ваше доказательство — это состояние плюс маршрут, указывающий на туннель.

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