Files
homelab-docs/docs/network/vpn-mobileconfig-wireguard.md
2026-02-25 21:01:06 +03:00

12 KiB
Raw Blame History

Генерация .mobileconfig для WireGuard VPN (On-Demand)

Как собрать Apple-профиль конфигурации (.mobileconfig) для WireGuard с правилами On-Demand: автоматическое подключение VPN вне домашней сети и отключение на домашнем WiFi.


Зачем нужен .mobileconfig

  • Обычный конфиг WireGuard — пользователь сам включает/выключает туннель.
  • Профиль .mobileconfig — ставится в «Настройки» → «Профили» (macOS) или «Основные» → «VPN и управление устройством» (iOS). Туннель появляется в приложении WireGuard и может управляться On-Demand: система сама поднимает VPN, когда устройство не в доверенной сети (например не дома), и отключает на домашнем WiFi.

В итоге: за пределами дома — всегда VPN, дома — без VPN, без ручного переключения.


Что должно быть готово на сервере

  • WireGuard поднят (например на контейнере 109).
  • Для каждого клиента (macOS, iOS и т.д.):
    • своя пара ключей (приватный + публичный);
    • в wg0.conf на сервере добавлен [Peer] с PublicKey и AllowedIPs (один адрес из подсети VPN, например 10.10.99.2/32 для iOS, 10.10.99.3/32 для macOS).
  • Внешний IP и порт сервера (например 185.35.193.144:43123), проброс UDP на роутере на CT 109.

Подсеть VPN в примерах: 10.10.99.0/24; DNS в туннеле — AdGuard на 192.168.1.100.


Структура профиля

Файл .mobileconfig — это XML plist (Property List) с корневым словарём:

Ключ Назначение
PayloadContent Массив payloadов (в нашем случае один — VPN).
PayloadDisplayName Название профиля в списке профилей.
PayloadIdentifier Уникальный идентификатор (например ru.katykhin.wireguard.local-vpn).
PayloadType Configuration.
PayloadUUID Уникальный UUID профиля.
PayloadVersion 1.

Внутри PayloadContent — один элемент типа VPN:

Ключ Назначение
PayloadType com.apple.vpn.managed
VPNSubType macOS: com.wireguard.macosiOS: com.wireguard.ios
UserDefinedName Имя туннеля в приложении WireGuard (например «Local VPN (WireGuard)»).
VendorConfigWgQuickConfig Строка с конфигом WireGuard в формате INI (как в обычном конфиге).
VPNRemoteAddress Адрес сервера (хост:порт).
OnDemandEnabled 1 — включить On-Demand.
OnDemandRules Массив правил: когда отключать VPN (например на домашнем WiFi) и когда подключать.

Конфиг WireGuard внутри профиля (WgQuickConfig)

В WgQuickConfig вставляется ровно тот же текст, что и в обычном клиентском конфиге WireGuard, например:

[Interface]
Address = 10.10.99.3/32
PrivateKey = <приватный-ключ-этого-клиента>
DNS = 192.168.1.100

[Peer]
PublicKey = <публичный-ключ-сервера>
Endpoint = 185.35.193.144:43123
AllowedIPs = 10.10.99.0/24, 192.168.1.0/24
PersistentKeepalive = 25
  • Address — один адрес из подсети VPN, уникальный для каждого устройства (в wg0.conf на сервере в AllowedIPs для этого peer должен быть этот же /32).
  • PrivateKey — приватный ключ клиента (генерируется один раз и хранится только на устройстве / в профиле).
  • PublicKey — публичный ключ сервера (из /etc/wireguard/server.pub на сервере).
  • Endpoint — внешний IP или домен и порт WireGuard (проброс на роутере).
  • AllowedIPs — какие сети пускать через VPN (подсеть VPN + LAN, если нужен доступ в домашнюю сеть).
  • PersistentKeepalive — полезно для мобильных и NAT.

Ключи в профиле — секретные; не коммитить .mobileconfig с реальными ключами в репозиторий (добавить в .gitignore).


Правила On-Demand (OnDemandRules)

Массив словарей. Порядок важен: первое сработавшее правило применяется.

  1. Отключить VPN на домашнем WiFi — правило с Action = Disconnect и условием по WiFi:

    • InterfaceTypeMatch = WiFi;
    • SSIDMatch = массив SSID (например ["HomeWiFi"] или ["Netcraze-1882"]).
    • Итог: если устройство в WiFi с этим SSID → VPN отключается.
  2. Во всех остальных случаях — подключать — правило без условий:

    • Action = Connect.
    • Итог: любой другой сеть (другой WiFi, сотовые данные) → VPN включается.

Пример в plist:

<key>OnDemandRules</key>
<array>
  <dict>
    <key>Action</key>
    <string>Disconnect</string>
    <key>InterfaceTypeMatch</key>
    <string>WiFi</string>
    <key>SSIDMatch</key>
    <array>
      <string>HomeWiFi</string>
    </array>
  </dict>
  <dict>
    <key>Action</key>
    <string>Connect</string>
  </dict>
</array>

Перед установкой профиля замени HomeWiFi на реальный SSID своей домашней сети.


Различия macOS и iOS

  • VPNSubType:
    • macOS: com.wireguard.macos
    • iOS: com.wireguard.ios
  • Остальная структура (WgQuickConfig, OnDemandRules, SSIDMatch) — одинаковая. Обычно делают два файла: wireguard-macos-ondemand.mobileconfig и wireguard-ios-ondemand.mobileconfig, в каждом свой клиентский ключ и свой Address (например .2/32 для iOS, .3/32 для macOS), если на сервере заведены два разных peerа.

Шаблон plist (минимум для одного туннеля)

Ниже — скелет без подстановки ключей; в WgQuickConfig и в SSIDMatch нужно подставить свои значения.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadContent</key>
  <array>
    <dict>
      <key>PayloadDisplayName</key>
      <string>VPN</string>
      <key>PayloadType</key>
      <string>com.apple.vpn.managed</string>
      <key>PayloadVersion</key>
      <integer>1</integer>
      <key>PayloadIdentifier</key>
      <string>ru.katykhin.wireguard.local-vpn.tunnel</string>
      <key>PayloadUUID</key>
      <string>A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D</string>
      <key>UserDefinedName</key>
      <string>Local VPN (WireGuard)</string>
      <key>VPNType</key>
      <string>VPN</string>
      <key>VPNSubType</key>
      <string>com.wireguard.macos</string>
      <key>VendorConfig</key>
      <dict>
        <key>WgQuickConfig</key>
        <string>[Interface]
Address = 10.10.99.3/32
PrivateKey = ВСТАВЬРИВАТНЫЙ_КЛЮЧ_КЛИЕНТА
DNS = 192.168.1.100

[Peer]
PublicKey = ВСТАВЬУБЛИЧНЫЙ_КЛЮЧ_СЕРВЕРА
Endpoint = 185.35.193.144:43123
AllowedIPs = 10.10.99.0/24, 192.168.1.0/24
PersistentKeepalive = 25
</string>
      </dict>
      <key>VPN</key>
      <dict>
        <key>RemoteAddress</key>
        <string>185.35.193.144:43123</string>
        <key>AuthenticationMethod</key>
        <string>Password</string>
      </dict>
      <key>OnDemandEnabled</key>
      <integer>1</integer>
      <key>OnDemandRules</key>
      <array>
        <dict>
          <key>Action</key>
          <string>Disconnect</string>
          <key>InterfaceTypeMatch</key>
          <string>WiFi</string>
          <key>SSIDMatch</key>
          <array>
            <string>HomeWiFi</string>
          </array>
        </dict>
        <dict>
          <key>Action</key>
          <string>Connect</string>
        </dict>
      </array>
    </dict>
  </array>
  <key>PayloadDisplayName</key>
  <string>WireGuard Local VPN (On-Demand)</string>
  <key>PayloadIdentifier</key>
  <string>ru.katykhin.wireguard.local-vpn</string>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadUUID</key>
  <string>B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>

Для iOS замени VPNSubType на com.wireguard.ios и в WgQuickConfig задай свой Address (например 10.10.99.2/32) и приватный ключ того peerа, который добавлен для этого устройства в wg0.conf.


Генерация ключей (на сервере)

На сервере WireGuard (например в CT 109):

# Приватный ключ
wg genkey | tee client.key | wg pubkey > client.pub

# Вывести для копирования в профиль
cat client.key   # → PrivateKey в [Interface]
cat /etc/wireguard/server.pub   # → PublicKey в [Peer]

Отдельные ключи для каждого устройства (например ios.key/macos.key) и соответствующие peerы в wg0.conf — см. контейнер 109.


Безопасность

  • В .mobileconfig попадают приватные ключи клиента. Файл нужно хранить только на доверенных носителях и не коммитить в публичный репозиторий.
  • В этом проекте файлы *.mobileconfig и конкретно wireguard-macos-ondemand.mobileconfig, wireguard-ios-ondemand.mobileconfig добавлены в .gitignore.
  • Передавать профиль на устройство по защищённому каналу (AirDrop, личная почта, зашифрованный диск).

Установка профиля

  • macOS: двойной клик по .mobileconfig → откроются «Системные настройки» → «Профили» → установить. Туннель появится в приложении WireGuard; при необходимости один раз включите его вручную, далее On-Demand будет управлять подключением.
  • iOS: отправить файл на устройство (AirDrop, почта, «Файлы») → открыть → «Установить» → при необходимости «Настройки» → «Основные» → «VPN и управление устройством» → установить профиль. Туннель появится в WireGuard; включите один раз вручную, затем работает On-Demand.

После смены SSID или ключей — удалить старый профиль и установить новый.


Связь с другими документами