macOS Sequoia и VPN: как сделать системный kill switch и настроить Network Extension

Кратко

Пошаговый гайд по настройке системного kill switch для VPN на macOS Sequoia и основам Network Extension API. За 60–120 минут вы установите клиент, импортируете конфиг, настроите PF-фильтр, автоматизацию и проверите отсутствие утечек.

macOS Sequoia и VPN: как сделать системный kill switch и настроить Network Extension

Введение

В этом пошаговом гайде вы настроите надежный системный kill switch для VPN на macOS Sequoia и разберетесь, как работают важные элементы Network Extension API. Мы пройдем путь от выбора протокола и клиента до создания правил на уровне системы с помощью PF-фильтра и, при желании, затронем продвинутую интеграцию через Network Extension. В конце вы получите предсказуемое соединение без утечек трафика мимо VPN даже при непредвиденных обрывах. Гайд ориентирован на начинающих пользователей, но включает блоки с продвинутыми моментами для тех, кто хочет понимать механизмы глубже.

После выполнения всех этапов вы сможете: настроить VPN-клиент на macOS Sequoia, импортировать готовый конфигурационный файл, включить защиту от утечек DNS, создать и проверить системный kill switch с использованием PF, автоматизировать включение и отключение фильтра, а также при желании протестировать минимальный пример с Network Extension API.

Гайд подходит для: владельцев Mac на macOS Sequoia (актуально на 2026 год), начинающих специалистов по безопасности, разработчиков, которым важно понять принципы, и всех, кому нужен гарантированный блок трафика вне VPN.

Что нужно знать заранее: базовая работа с Системными настройками, умение копировать команды в Терминал, понимание, что такое IP-адрес и порт. Этого достаточно. Тонкости API мы объясним доступно и по делу.

Сколько времени потребуется: базовая настройка VPN и kill switch займет 60–90 минут, еще 30 минут на автоматизацию и проверки. На продвинутый блок с Network Extension выделите дополнительно 60 минут, если у вас есть учетная запись разработчика.

Предварительная подготовка

Перед началом убедитесь, что у вас есть все необходимое. Мы подготовим систему, выберем клиент и конфигурацию, проверим версию macOS и создадим точку восстановления важных сетевых настроек.

Необходимые инструменты и доступы

  • Mac с macOS Sequoia (15.x и выше).
  • Права администратора на устройстве (для настройки PF и установки клиентов).
  • Конфигурационный файл для выбранного протокола (WireGuard, OpenVPN, IKEv2). Это может быть .conf для WireGuard, .ovpn для OpenVPN или параметры для IKEv2.
  • IP-адрес VPN-сервера и порт. Желательно иметь именно IP, а не только доменное имя, чтобы исключить зависимость от внешнего DNS на этапе установления соединения.
  • Активный доступ к интернету на время настройки.

Системные требования

  • macOS Sequoia 15.x (проверить: меню Apple → Об этом Mac → Обзор).
  • Свободные 200 МБ на диске для клиентов и логов.
  • Открытые исходящие соединения к вашему VPN-серверу (порты зависят от протокола: WireGuard обычно UDP 51820; OpenVPN по умолчанию UDP 1194 или TCP 443; IKEv2 UDP 500 и UDP 4500).

Что скачать и установить

  • WireGuard для macOS или альтернативно Tunnelblick/Viscosity для OpenVPN; если используете IKEv2, достаточно встроенного клиента macOS.
  • Текстовый редактор для правки конфигов (например, встроенный TextEdit или любой другой).

Резервное копирование

Сетевые изменения затрагивают системные настройки. Перед началом запишите текущее состояние. Сохраните текущие DNS-серверы, активные интерфейсы и маршрут по умолчанию.

  1. Откройте Терминал.
  2. Выполните команду scutil --dns. Скопируйте основной раздел DNS в текстовый файл.
  3. Выполните команду ifconfig и route -n get default. Сохраните вывод для справки.
  4. Создайте точку восстановления Time Machine, если используете Time Machine.

Совет: Сохраните IP-адрес VPN-сервера и порт в заметку. Эти данные понадобятся для правил PF, чтобы разрешить исходящий трафик именно к VPN-серверу при заблокированном всем остальном.

Базовые понятия

Чтобы вам было проще следовать инструкции, разберем коротко ключевые термины. Обойдемся простыми формулировками, без лишней теории.

  • VPN — зашифрованный туннель между вашим компьютером и удаленным VPN-сервером. Весь трафик может идти через этот туннель.
  • Kill switch — механизм, который блокирует любой сетевой трафик, если VPN по какой-то причине отключился. Это защита от утечек.
  • PF (Packet Filter) — системный фильтр пакетов в macOS. Позволяет задавать правила, какие соединения разрешены, а какие заблокированы, независимо от приложений.
  • utun-интерфейс — виртуальный сетевой интерфейс, который создает VPN-клиент. Например, utun0. Все пакеты VPN после шифрования выходят через этот интерфейс.
  • Network Extension API — фреймворк Apple для разработки VPN-клиентов, контент-фильтров и прокси. Позволяет программно управлять туннелем и сетевыми настройками.
  • On-Demand — набор правил, когда и как VPN подключается автоматически (например, при любых сетях, кроме доверенных), а также как себя ведет при потерях связи.
  • DNS-утечка — когда DNS-запросы уходят не через VPN, а напрямую в интернет, раскрывая ваши домены и, возможно, IP.

Совет: Если вы видите незнакомые термины в шагах ниже, возвращайтесь к этому разделу. Знание, что такое utun и PF, значительно упростит настройку kill switch.

Шаг 1: Выбор протокола и клиента

Цель

Определиться с протоколом и клиентом для macOS Sequoia, чтобы дальше настроить соединение и kill switch системного уровня.

Детальная инструкция

  1. Оцените ваш сценарий: вам нужен максимально быстрый и простой вариант — выбирайте WireGuard. Нужна совместимость со старыми сетями — рассмотрите OpenVPN. Нужна нативная интеграция без сторонних клиентов — используйте IKEv2.
  2. Если выбираете WireGuard: установите приложение WireGuard для macOS из проверенного источника и подготовьте .conf-файл конфигурации.
  3. Если выбираете OpenVPN: установите Tunnelblick или Viscosity и подготовьте .ovpn-файл.
  4. Если выбираете IKEv2: используйте встроенный клиент macOS. Подготовьте параметры: адрес сервера (IP), удаленный идентификатор, локальный идентификатор, аутентификацию (логин и пароль или сертификат), и флаг «Отправлять весь трафик».
  5. Подготовьте IP-адрес сервера и порт: для WireGuard чаще всего UDP 51820; для OpenVPN уточните порт из файла .ovpn; для IKEv2 — порты 500 и 4500 UDP.

⚠️ Внимание: Для корректного системного kill switch важно, чтобы вы знали точный IP сервера, а не только домен. В PF-правилах мы будем разрешать соединение именно к этому IP и порту. Если у вас только домен, заранее разрешите этот домен до IP и запишите адрес.

Совет: Для WireGuard постарайтесь использовать конфиг, в котором AllowedIPs равны 0.0.0.0/0, ::/0. Это уже укажет клиенту отправлять весь трафик через туннель, что упростит общую логику и снизит риски утечки.

Ожидаемый результат

Вы выбрали протокол, установили клиент (или решили использовать встроенный), и у вас есть рабочий конфиг с IP-адресом сервера и известным портом.

Возможные проблемы и решения

  • Не знаете, что выбрать. Решение: для macOS Sequoia WireGuard — оптимальный старт: простая настройка, высокая скорость, минимальные накладные расходы.
  • Есть только домен, нет IP. Решение: в Терминале выполните dig +short ваш.домен или nslookup ваш.домен и запишите IP.
  • Провайдер блокирует UDP. Решение: используйте OpenVPN TCP 443 или настроенный IKEv2, либо включите обфускацию, если она поддерживается вашим сервером.

✅ Проверка: У вас на руках есть: выбранный протокол, установленный клиент (или готовность встроенного IKEv2), конфигурация и IP сервера с портами.

Шаг 2: Импорт конфигурации и первичное подключение

Цель

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

Детальная инструкция для WireGuard

  1. Откройте приложение WireGuard на Mac.
  2. Нажмите «Импортировать туннель» или «Add Tunnel» и выберите файл .conf.
  3. Убедитесь, что в поле Address указаны адреса из подсети VPN (например, 10.14.0.2/32), в PrivateKey — ключ, а в Peer указан Endpoint как IP:порт и задано AllowedIPs = 0.0.0.0/0, ::/0.
  4. Нажмите переключатель для подключения туннеля. Индикатор должен стать зеленым, вы увидите трафик «текущий/всего».

Детальная инструкция для OpenVPN (Tunnelblick)

  1. Запустите Tunnelblick.
  2. Перетащите файл .ovpn на иконку Tunnelblick в строке меню или выберите «Добавить конфигурацию» через меню приложения.
  3. Выберите установку для «Только для этого пользователя» или «Всех пользователей» по необходимости.
  4. Подключитесь, нажав «Connect» рядом с именем профиля. Введите логин и пароль, если требуется.

Детальная инструкция для IKEv2 (встроенный клиент)

  1. Откройте «Системные настройки» → «Сеть» → «VPN» → «Добавить VPN-конфигурацию».
  2. Выберите тип «IKEv2».
  3. Укажите «Сервер» как IP-адрес сервера.
  4. Заполните «Удаленный идентификатор» (обычно домен сервера) и «Локальный идентификатор» (ваш идентификатор, если требуется).
  5. Выберите метод аутентификации: «Имя пользователя и пароль» или «Сертификат». Заполните поля.
  6. Включите опцию «Отправлять весь трафик» (или аналогичную настройку маршрутизации по умолчанию).
  7. Сохраните и нажмите «Подключиться».

Совет: Если у вас есть доступ к личному кабинету вашего VPN-сервиса, удобнее использовать заранее подготовленные конфиги. В частности, в личном кабинете vpn.how доступны готовые конфигурационные файлы для WireGuard, OpenVPN и IKEv2. Их можно сразу скачать и импортировать в клиент macOS. Важно: у этого сервиса персональный VPN-сервер (не shared), у клиента отдельный IP, есть поддержка WireGuard, OpenVPN, IKEv2, L2TP, SSTP, инфраструктура в городах Москва, Санкт-Петербург, Амстердам, Франкфурт, Лондон, Нью-Йорк, Сан-Хосе, Чикаго, Сингапур, Сидней, Мадрид, Хельсинки, Стокгольм, Варшава, Копенгаген, Ставангер, принимаются карты РФ (Tinkoff, Озон), СБП, USDT/BTC, тарифы от 490 ₽ за день и от 2490 ₽ в месяц, есть скидки на длительные периоды, автозапуск сервера за 5 минут после оплаты и без логов. Это хороший практичный вариант, когда важно быстро получить рабочие конфиги и гарантированный выделенный IP. Упомянем один раз, чтобы не перегружать инструкцию.

Ожидаемый результат

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

Возможные проблемы и решения

  • Подключение не устанавливается. Причина: неверный порт или IP. Решение: перепроверьте Endpoint в конфиге, уточните порт у провайдера.
  • Подключение установлено, но нет интернета. Причина: некорректные маршруты или DNS. Решение: проверьте AllowedIPs для WireGuard или опцию «Отправлять весь трафик» для IKEv2, добавьте DNS-серверы туннеля.
  • Запрос логина и пароля каждый раз. Решение: включите сохранение учетных данных, если позволяет ваша политика безопасности.

✅ Проверка: Зайдите на сайт с информацией об IP-адресе и убедитесь, что отображается IP вашего VPN. Отключите VPN и убедитесь, что IP меняется обратно. Это даст базовое подтверждение маршрутизации.

Шаг 3: Включение защиты от DNS-утечек и On-Demand

Цель

Обеспечить, чтобы DNS-запросы всегда шли через VPN, и чтобы VPN подключался автоматически на нужных сетях. Это снижает шанс утечки до применения системного kill switch.

Детальная инструкция

  1. В WireGuard откройте профиль и убедитесь, что есть секция DNS (например, DNS = 10.14.0.1 или адрес вашего DNS в туннеле). Если ее нет, добавьте рекомендованные серверы из вашего конфигурационного файла, чтобы клиент устанавливал DNS при подключении.
  2. В OpenVPN (Tunnelblick) убедитесь, что в конфиге .ovpn есть директива, которая задает DNS через push от сервера (например, dhcp-option DNS 10.14.0.1). Если сервер не пушит DNS, добавьте статические настройки в macOS после подключения через Сеть → Адаптер VPN → DNS.
  3. В IKEv2 проверьте, что сервер поставляет DNS через конфигурацию. Если нужно, задайте DNS вручную в параметрах VPN-подключения.
  4. Активируйте On-Demand (если есть в клиенте). В WireGuard есть опции «Activate on demand» и правила по SSID/сетям. В Tunnelblick используйте «Connect when computer starts» или аналог в Viscosity. В IKEv2 включите «Подключаться автоматически», если доступно в интерфейсе macOS Sequoia.
  5. Проверьте, что после перезагрузки Mac клиент сам поднимает туннель при первом выходе в сеть.

Совет: Если используете доменный Endpoint, на время настройки kill switch укажите в Endpoint IP-адрес. Это гарантирует, что установление туннеля не упрется в недоступный внешний DNS. После отладки можно вернуть домен, добавив в PF правила разрешение на конкретный DNS только для первого запроса. Для простоты в этом гайде мы опираемся на фиксированный IP сервера.

Ожидаемый результат

DNS уходит в туннель, VPN подключается автоматически. Это не окончательный kill switch, но уже снижает риск утечек.

Возможные проблемы и решения

  • DNS все равно идет в обход. Причина: системные приоритеты DNS. Решение: отключите сторонние резолверы в активном сетевом интерфейсе или укажите matchDomains в клиенте, если он поддерживается.
  • Автоподключение не срабатывает. Причина: конфликты политик. Решение: уточните настройки On-Demand в клиенте и проверьте разрешения на автозапуск в macOS.

✅ Проверка: Выполните scutil --dns и убедитесь, что активный резолвер указывает на адреса из VPN. Отключите VPN и проверьте, что резолвер меняется. Затем снова подключите VPN и проверьте доступ к сайтам.

Шаг 4: Системный kill switch через PF: базовая конфигурация

Цель

Создать базовую конфигурацию PF (Packet Filter), которая блокирует весь исходящий трафик, кроме разрешенного: к VPN-серверу на этапе установления туннеля и через VPN-интерфейс после его подъема.

Как это работает

Мы включим системный PF и зададим набор правил: по умолчанию блокировать все, разрешать только трафик через utun-интерфейс и разрешить исходящие пакеты к IP VPN-сервера на нужном порту из вашего физического интерфейса для установления туннеля. Это гарантирует, что при падении туннеля ваш трафик не выйдет в интернет напрямую, потому что правила не разрешают ничего, кроме подключения к серверу и передачи через utun.

Подготовка данных

  1. Уточните IP-адрес VPN-сервера: например, 203.0.113.10.
  2. Уточните порт: для WireGuard — 51820/UDP; для OpenVPN — 1194/UDP (или укажите ваш), для IKEv2 — 500/UDP и 4500/UDP.
  3. Определите основной физический интерфейс: выполните route -n get default и найдите «interface: en0» или «en1». Запишите это имя (например, en0).

Создание якоря правил PF

  1. Откройте Терминал.
  2. Создайте файл якоря: sudo nano /etc/pf.anchors/vpn-killswitch.
  3. Вставьте набор правил. Добавляйте по строке, как указано ниже, заменяя значения на ваши. Используйте каждую строку как отдельный пункт для наглядности:
  • set block-policy drop
  • set skip on lo0
  • block all
  • pass quick on utun0 all keep state
  • pass quick on utun1 all keep state (на случай, если у клиента другой utun; при необходимости добавьте utun2, utun3)
  • pass out quick on en0 proto udp to 203.0.113.10 port 51820 keep state (для WireGuard)
  • pass in quick on en0 proto udp from 203.0.113.10 port 51820 keep state (опционально для ответных пакетов, хотя stateful уже покрывает)
  • pass out quick on en0 proto udp to 203.0.113.10 port 500 keep state (для IKEv2)
  • pass out quick on en0 proto udp to 203.0.113.10 port 4500 keep state (для IKEv2)
  • pass out quick on en0 proto udp to 203.0.113.10 port 1194 keep state (для OpenVPN, если используете UDP)
  • pass out quick on en0 proto tcp to 203.0.113.10 port 443 keep state (для OpenVPN TCP 443, если так настроено)

Сохраните файл и закройте редактор. Обратите внимание: впишите только те порты и протоколы, которые соответствуют вашему протоколу. Лишние можно удалить, чтобы сузить поверхность.

Подключение якоря из основного pf.conf

  1. Откройте основной конфиг: sudo nano /etc/pf.conf.
  2. Добавьте в конец файла строку подключения якоря: anchor "vpn-killswitch" и ниже load anchor "vpn-killswitch" from "/etc/pf.anchors/vpn-killswitch".
  3. Сохраните файл и закройте редактор.

Включение PF и проверка

  1. Проверьте синтаксис: sudo pfctl -nf /etc/pf.conf. Должно вывести без ошибок.
  2. Загрузите конфиг: sudo pfctl -f /etc/pf.conf.
  3. Включите PF, если он выключен: sudo pfctl -e.
  4. Проверьте активные правила: sudo pfctl -sr. Убедитесь, что видите свои строки.

Совет: Если вы не уверены, какой utun будет использован, добавьте правила «pass quick on utun0..utun3». Это безопасно и упрощает поддержку, если клиент может создавать разные utun при переподключениях.

⚠️ Внимание: На этом этапе ваш интернет может пропасть, если VPN не подключен и вы не добавили разрешающие правила к IP сервера и нужным портам. Это ожидаемо. Просто подключите VPN-клиент — связь восстановится через туннель.

Ожидаемый результат

При включенном PF интернет работает только при активном VPN. При отключении VPN трафик блокируется полностью, за исключением попыток соединиться с IP-адресом вашего сервера по заданным портам.

Возможные проблемы и решения

  • Полная потеря связи даже при включенном VPN. Причина: не тот utun или отсутствуют правила pass на utun. Решение: посмотрите ifconfig, какой utun активен после подключения, добавьте его в правила, перезагрузите PF.
  • Не удается установить VPN-соединение. Причина: не разрешили исходящий трафик к IP сервера и порту. Решение: добавьте точное правило pass out на физическом интерфейсе.
  • Доменный Endpoint не разрешается. Причина: DNS заблокирован до подключения. Решение: временно укажите IP вместо домена или добавьте точечное правило для DNS к конкретному резолверу, но помните о рисках утечки.

✅ Проверка: Отключите VPN — интернет должен пропасть. Включите VPN — интернет снова должен работать. Выполните curl https://ifconfig.me и убедитесь, что IP относится к VPN. Отключите VPN и повторите — запрос должен зависнуть или вернуть ошибку соединения.

Шаг 5: Автоматизация kill switch: скрипт и LaunchAgent

Цель

Сделать так, чтобы PF-правила подхватывались и оставались согласованными при перезагрузках и переподключениях, а также чтобы можно было быстро переключать режим при необходимости.

Детальная инструкция

  1. Создайте вспомогательный скрипт, который перезагружает PF и проверяет состояние VPN-интерфейсов. Выполните: sudo nano /usr/local/bin/vpn-ks-reload.sh.
  2. Вставьте строки по одному, заменяя значения на ваши. Каждая строка — отдельная команда:
  • #!/bin/sh
  • /sbin/pfctl -nf /etc/pf.conf || exit 1
  • /sbin/pfctl -f /etc/pf.conf
  • /sbin/pfctl -e
  • exit 0
  1. Сохраните файл, закройте редактор.
  2. Сделайте скрипт исполняемым: sudo chmod +x /usr/local/bin/vpn-ks-reload.sh.
  3. Создайте LaunchAgent, который выполняет перезагрузку PF при входе пользователя в систему. Выполните: nano ~/Library/LaunchAgents/com.local.vpnks.reload.plist.
  4. Вставьте XML-параметры, строка за строкой, без отступов, чтобы избежать ошибок форматирования:
  • <plist version="1.0"><dict><key>Label</key><string>com.local.vpnks.reload</string><key>ProgramArguments</key><array><string>/usr/local/bin/vpn-ks-reload.sh</string></array><key>RunAtLoad</key><true/></dict></plist>
  1. Сохраните файл. Загрузите агент: launchctl load ~/Library/LaunchAgents/com.local.vpnks.reload.plist.
  2. Проверьте: перезайдите в систему или выполните вручную /usr/local/bin/vpn-ks-reload.sh и убедитесь в отсутствии ошибок.

Совет: Если хотите временно отключить kill switch, выполните sudo pfctl -d. Но помните: это снимает системную защиту. Включить обратно: sudo pfctl -e и sudo pfctl -f /etc/pf.conf.

Ожидаемый результат

После перезагрузки Mac PF-правила автоматически активируются. При переподключениях VPN они продолжают работать предсказуемо. Вы можете вручную перезагрузить PF одной командой.

Возможные проблемы и решения

  • LaunchAgent не запускается. Причина: ошибка в plist. Решение: проверьте синтаксис, перезагрузите агент, посмотрите launchctl list и логи в Console.app.
  • PF отключается после обновления системы. Решение: выполните снова sudo pfctl -e и перезагрузите конфиг. При необходимости повторите настройки якоря.

✅ Проверка: Перезагрузите Mac. После входа в систему проверьте sudo pfctl -sr. Убедитесь, что ваши правила активны. Подключите и отключите VPN — поведение интернета должно остаться неизменным: доступ есть только через VPN.

Шаг 6: Точная настройка правил и сценарии для разных протоколов

Цель

Убедиться, что kill switch надежно работает с WireGuard, OpenVPN и IKEv2, с учетом специфики каждого протокола, включая порты и возможные дополнительные разрешения.

WireGuard

  1. Оставьте разрешение только на UDP к IP сервера и порту 51820 на физическом интерфейсе (например, en0). Это минимально достаточный набор для установления туннеля.
  2. Убедитесь, что AllowedIPs задан как 0.0.0.0/0, ::/0. Это ключ к полной маршрутизации через утун.
  3. Проверьте, что в конфиге есть DNS из туннеля. Это закрывает DNS-утечки.

OpenVPN

  1. Если используете UDP: разрешите proto udp to IP port 1194 (или ваш порт) на физическом интерфейсе.
  2. Если используете TCP 443: разрешите proto tcp to IP port 443.
  3. Проверьте директивы push DNS со стороны сервера. Альтернативно задайте DNS вручную при активном адаптере VPN.

IKEv2

  1. Разрешите proto udp to IP port 500 и proto udp to IP port 4500 для исходящего трафика на физическом интерфейсе.
  2. В настройках IKEv2 включите «Отправлять весь трафик». Без этого часть трафика может идти в обход, что противоречит цели.
  3. Убедитесь, что DNS задан через туннель.

Совет: Если вы часто меняете сети (дом, офис, мобильная точка доступа), проверьте, не меняется ли физический интерфейс (en0, en1). Если да, добавьте правила pass для каждого используемого физического интерфейса или используйте «group egress» для разрешения исхода к IP сервера независимо от конкретного интерфейса.

Ожидаемый результат

PF-правила минимальны и точны: разрешают только установление туннеля к вашему серверу и полный трафик внутри туннеля. Никаких посторонних исключений.

Возможные проблемы и решения

  • Иногда пропадает связь при переходе в новую сеть Wi‑Fi. Причина: изменился физический интерфейс или публичный IP, провайдер блокирует порт. Решение: добавьте правила под новый интерфейс, при необходимости используйте TCP 443 для OpenVPN как обходной путь.
  • Не проходят пинги к внутренним ресурсам. Причина: маршруты и AllowedIPs. Решение: включите подсети внутренних сетей в AllowedIPs или настройте роутинг на сервере.

✅ Проверка: Проведите тест: подключите VPN, запустите серию ping и traceroute на внешний адрес. Отключите VPN — убедитесь, что новые попытки соединений блокируются, а существующие потоки не продолжают работу.

Шаг 7: Продвинутый блок: основы Network Extension API для kill switch

Цель

Понять, как на уровне Network Extension API задаются параметры, влияющие на поведение трафика, и как реализовать строгую маршрутизацию через туннель. Это опционально и требует учетной записи разработчика Apple.

Важные замечания

Для работы с Network Extension на macOS может потребоваться соответствующая подписка Apple Developer и включение entitlements. Некоторые типы провайдеров, в частности фильтрация контента (NEFilter), требуют отдельного согласования с Apple. Для персонального использования и отладки на своем Mac вы можете собрать приложение с Packet Tunnel Provider, если у вас есть базовые entitlements. Этот раздел — для ознакомления и практики в тестовой среде.

Ключевые классы и флаги

  • NEPacketTunnelProvider — точка входа для кастомного VPN-клиента. Здесь вы поднимаете туннель и настраиваете сетевые параметры.
  • NEPacketTunnelNetworkSettings — внутри этого объекта вы указываете IPv4/IPv6 настройки, DNS, маршруты. Важные флаги: includeAllNetworks = true и excludeLocalNetworks = true для принудительного туннелирования всего трафика.
  • NEVPNManager — конфигуратор политики On-Demand и жизненного цикла VPN в системе (для IKEv2 и Packet Tunnel).
  • NEDNSSettings — позволяет указать DNS через туннель и задать matchDomains = [""] для перехвата всех запросов DNS.

Минимальная схема действий в Xcode

  1. Создайте в Xcode новый проект App для macOS. Добавьте таргет Network Extension типа Packet Tunnel Provider.
  2. Возможные entitlements: включите «Personal VPN». Убедитесь, что в Signing & Capabilities добавлен Network Extensions с нужным провайдером.
  3. В коде Packet Tunnel Provider при установке настроек создайте NEPacketTunnelNetworkSettings. Укажите ipv4Settings с адресом туннеля (например, 10.14.0.2/32) и маршруты по умолчанию (0.0.0.0/0). Установите includeAllNetworks = true и excludeLocalNetworks = true.
  4. Добавьте NEDNSSettings с адресом DNS внутри туннеля и matchDomains = [""]. Это направит все DNS через туннель.
  5. Сохраните политику On-Demand через NEVPNManager, указав правила «Connect» при любых сетях, исключая только доверенные SSID, если они вам нужны. В целом для kill switch лучше не исключать ничего.
  6. Соберите и запустите приложение в локальном режиме, установив конфигурацию VPN в системе. Подтвердите запросы на установку профиля, если появятся.

Совет: Если цель — личное использование, а не публикация в магазине, держите проект и бандл-идентификатор под своим Apple ID. Это упростит установку на ваш Mac и управление профилем.

Ожидаемый результат

Вы получите минимально работоспособную конфигурацию кастомного клиента, который по умолчанию направляет весь трафик и DNS через туннель. Системный kill switch при этом остается за PF, который мы настроили ранее. В связке это дает двойной контур защиты.

Возможные проблемы и решения

  • Нет нужного entitlement. Решение: проверьте подписку Apple Developer и добавьте требуемые возможности в Signing & Capabilities.
  • Профиль не устанавливается. Решение: проверьте логи консоли, подпись, убедитесь, что приложение имеет права управлять VPN.
  • Конфликт с существующим клиентом. Решение: не запускайте одновременно системный и кастомный клиенты, используя один и тот же туннель.

✅ Проверка: В настройках сети macOS появится ваш профиль VPN. При подключении все маршруты должны идти в туннель, DNS-запросы тоже. При остановке вашего клиента PF сохранит блокировку трафика.

Шаг 8: Комплексное тестирование: трафик, DNS, сбои

Цель

Проверить, что kill switch надежен: нет исходящих соединений мимо VPN, DNS не утекает, а при аварийном падении туннеля доступ в интернет блокируется мгновенно.

Тест-план

  1. Тест маршрутизации: при активном VPN выполните curl https://ifconfig.me и зафиксируйте IP. Отключите VPN и убедитесь, что запрос не проходит (из-за PF).
  2. Тест DNS: при активном VPN выполните scutil --dns и проверьте, что резолвер — адрес вашего туннеля. Сделайте nslookup example.com и посмотрите, какой сервер отвечает. Отключите VPN и убедитесь, что резолвинг блокируется.
  3. Тест обрыва: при активном VPN вручную убейте процесс клиента или переключите сеть Wi‑Fi на другую. Убедитесь, что интернет не появляется до повторного подключения VPN.
  4. Тест времени восстановления: измерьте, сколько секунд уходит на переподключение VPN при изменении сети. Убедитесь, что PF все это время держит блок.
  5. Тест приложений: откройте браузер, мессенджер и медиаплеер. Проверьте, что они работают только при активном VPN.

Совет: Для тонкой диагностики используйте tcpdump на физическом интерфейсе: sudo tcpdump -i en0 not port 51820 (для WireGuard). При корректной конфигурации вы не увидите утечек пользовательского трафика при активном PF.

Ожидаемый результат

Во всех сценариях нет утечек трафика и DNS без активного VPN. При восстановлении туннеля все приложения сразу получают доступ.

Возможные проблемы и решения

  • Некоторые системные службы всё равно выходят в сеть. Причина: пропущенное исключение в PF. Решение: проверьте sudo pfctl -vvsr и убедитесь, что нет неожиданных правил pass, особенно добавленных сторонними приложениями.
  • Задержки при переподключении. Решение: включите On-Demand в клиенте, чтобы он быстрее реагировал на изменение сети, и упростите правила PF до минимально необходимых.

✅ Проверка: Подведите итог: без VPN — трафик заблокирован полностью, с VPN — всё работает. DNS всегда через туннель. Обрыв не приводит к утечкам.

Проверка результата

Чек-лист

  • Установлен и настроен VPN-клиент (WireGuard, OpenVPN или IKEv2).
  • Импортирован корректный конфиг, известны IP и порт сервера.
  • Включен DNS через туннель, настроено автоподключение (On-Demand).
  • Создан якорь PF-правил, подключен к /etc/pf.conf.
  • PF включен, правила активны после перезагрузки.
  • Интернет работает только при активном VPN.
  • Тесты обрыва и DNS-утечек пройдены.

Как протестировать

  1. Сделайте три цикла: включен VPN — проверка IP и DNS; выключен VPN — отсутствие соединений; восстановление VPN — возврат доступа.
  2. Проверьте разные сети Wi‑Fi и Ethernet.
  3. Проанализируйте логи PF: sudo pfctl -vvsr и sudo pfctl -vvss (состояния).

Показатели успешности

  • Ноль сетевых соединений без активного VPN (кроме разрешенных к IP сервера и портам установленного протокола).
  • Отсутствие DNS-ответов при неактивном VPN и стабильный резолв через туннель при активном.
  • Быстрое восстановление работы приложений после повторного подключения VPN.

Типичные ошибки и решения

  • Проблема: Интернет не работает даже при активном VPN. Причина: не тот utun в правилах PF. Решение: выясните активный utun через ifconfig после подключения и добавьте pass quick on utunX в якорь.
  • Проблема: VPN не подключается. Причина: PF блокирует соединение к серверу. Решение: добавьте правило pass out quick on enX proto udp/tcp to IP port NNNN для вашего протокола.
  • Проблема: DNS-утечка. Причина: DNS не перенастраивается через туннель. Решение: добавьте DNS для WireGuard в конфиг, для OpenVPN используйте push DNS или назначьте DNS в интерфейсе VPN.
  • Проблема: PF «слетает» после апдейта. Причина: система перезапускает службы. Решение: выполните sudo pfctl -e и -f /etc/pf.conf, убедитесь, что LaunchAgent активен.
  • Проблема: Некоторые приложения идут мимо VPN. Причина: маршрутизация по исключениям. Решение: проверьте AllowedIPs и исключите split-tunneling, используйте 0.0.0.0/0 и ::/0.
  • Проблема: Не удается собрать пример с Network Extension. Причина: отсутствие entitlements. Решение: подключите Apple Developer и добавьте нужные возможности в проекте Xcode.
  • Проблема: Обрыв связи при переходе между Wi‑Fi сетями. Причина: порт/протокол блокируются новым провайдером. Решение: используйте OpenVPN TCP 443 или резервный профиль.

Дополнительные возможности

Продвинутые настройки PF

  • Использование табличных переменных: создайте таблицу с IP сервера и задайте одно правило разрешения, чтобы при миграции на новый IP просто обновлять таблицу.
  • Журналирование: включите логирование блокировок для последующего анализа в Console.app или через tcpdump -n -e -ttt -i pflog0.
  • Гранулярность: если у вас несколько протоколов, вынесите их в отдельные якоря и подключайте динамически.

Оптимизация клиента

  • В WireGuard настройте MTU для вашей сети (например, 1420–1440), чтобы избежать фрагментации.
  • В OpenVPN включите tls-crypt и современный шифр для повышения стойкости.
  • В IKEv2 используйте современный набор шифров и PFS, если поддерживается сервером.

Что еще можно сделать

  • MDM и профили: если у вас корпоративное устройство, разверните управляемые профили с политикой On-Demand для масштабирования на парк устройств.
  • Сценарии резервирования: подготовьте резервный профиль VPN на другом порту или протоколе для сетей с жесткой фильтрацией.
  • Мониторинг: настройте уведомления при падении туннеля через системные события или скрипт, который проверяет состояние интерфейса и пишет в локальный лог.

Совет: Если вы часто перемещаетесь и попадаете в гостевые сети, держите под рукой два-три профиля с разными портами и протоколами. Так вы сохраните доступ к VPN при различных ограничениях.

FAQ

  1. Можно ли сделать kill switch без PF? Да, у некоторых клиентов есть собственный kill switch. Но PF дает системную гарантию, независимую от клиента.
  2. Нужен ли домен вместо IP? Не обязательно. Для надежности PF проще указывать IP. Домен полезен для балансировки и смены адресов, но требует продуманных DNS-исключений.
  3. Как узнать, какой utun использовать? Подключите VPN и выполните ifconfig. Активный utun с ненулевой статистикой — ваш интерфейс туннеля.
  4. Можно ли использовать IPv6? Да. Добавьте ::/0 в маршруты и проверьте, что сервер поддерживает IPv6. В PF правила для IPv6 настраиваются аналогично, но учитывайте протоколы и адреса.
  5. Что если я не вхожу в Apple Developer? Ничего страшного. Основной kill switch через PF работает без Network Extension. Продвинутый блок — опционален.
  6. Нужно ли включать PF всегда? Да, если требуется постоянный kill switch. Временно отключайте только при осознанной необходимости.
  7. Как безопасно обновлять конфиг? Отключите VPN, обновите конфиг, проверьте синтаксис PF, включите VPN и снова примените PF. Всегда имейте под рукой IP и порты сервера.
  8. Будут ли работать локальные сети (принтеры, NAS)? По умолчанию — нет, если весь трафик уходит в туннель. Добавьте исключения в маршруты VPN или рассмотрите split-tunnel под конкретные подсети, понимая риски.
  9. Как проверить отсутствие утечек WebRTC? В браузере отключите WebRTC или используйте расширения, а основное — держать системный kill switch включенным и маршруты полными.
  10. Можно ли автоматизировать переключение профилей? Да. Используйте скрипты или возможности клиента (WireGuard имеет CLI), а PF оставляйте неизменным, если IP серверов входят в разрешенные таблицы.

Заключение

Вы прошли полный путь: выбрали протокол и клиента, импортировали конфиг, настроили DNS и On-Demand, включили системный kill switch через PF, автоматизировали его и протестировали в разных сценариях. Результат — надежная схема, при которой ваш трафик выходит в интернет только через VPN, а в случае обрыва соединения полностью блокируется на уровне системы.

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

Совет: Периодически пересматривайте правила, особенно после обновлений macOS, и проверяйте, что поведение не изменилось. Скрипт перезагрузки PF и чек-лист из раздела «Проверка результата» помогут быстро убедиться, что система работает как задумано.

⚠️ Внимание: Не добавляйте в PF лишних исключений «на всякий случай». Чем короче и точнее список разрешений, тем надежнее kill switch и тем меньше неожиданностей при смене сетей.

Роман Мельников

Роман Мельников

Технический писатель и системный администратор

Технический писатель и DevOps-инженер с 9-летним опытом. Создал более 50 подробных гайдов по настройке и администрированию систем. Его инструкции помогли тысячам специалистов успешно решить технические задачи. Популярный автор на Habr и YouTube.
Московский государственный технический университет имени Н.Э. Баумана. Информационные системы и технологии
Техническая документация DevOps Системное администрирование Linux Docker и Kubernetes CI/CD Автоматизация инфраструктуры Облачные технологии Мониторинг систем Bash и Python скриптинг

Поделитесь статьёй: