259 lines
12 KiB
Markdown
259 lines
12 KiB
Markdown
# Генерация .mobileconfig для WireGuard VPN (On-Demand)
|
||
|
||
Как собрать Apple-профиль конфигурации (`.mobileconfig`) для WireGuard с правилами **On-Demand**: автоматическое подключение VPN вне домашней сети и отключение на домашнем Wi‑Fi.
|
||
|
||
---
|
||
|
||
## Зачем нужен .mobileconfig
|
||
|
||
- **Обычный конфиг WireGuard** — пользователь сам включает/выключает туннель.
|
||
- **Профиль .mobileconfig** — ставится в «Настройки» → «Профили» (macOS) или «Основные» → «VPN и управление устройством» (iOS). Туннель появляется в приложении WireGuard и может управляться **On-Demand**: система сама поднимает VPN, когда устройство не в доверенной сети (например не дома), и отключает на домашнем Wi‑Fi.
|
||
|
||
В итоге: за пределами дома — всегда VPN, дома — без VPN, без ручного переключения.
|
||
|
||
---
|
||
|
||
## Что должно быть готово на сервере
|
||
|
||
- WireGuard поднят (например на [контейнере 109](../containers/container-109.md)).
|
||
- Для каждого клиента (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.macos` — **iOS:** `com.wireguard.ios` |
|
||
| `UserDefinedName` | Имя туннеля в приложении WireGuard (например «Local VPN (WireGuard)»). |
|
||
| `VendorConfig` → `WgQuickConfig` | Строка с конфигом WireGuard в формате INI (как в обычном конфиге). |
|
||
| `VPN` → `RemoteAddress` | Адрес сервера (хост:порт). |
|
||
| `OnDemandEnabled` | `1` — включить On-Demand. |
|
||
| `OnDemandRules` | Массив правил: когда отключать VPN (например на домашнем Wi‑Fi) и когда подключать. |
|
||
|
||
---
|
||
|
||
## Конфиг WireGuard внутри профиля (WgQuickConfig)
|
||
|
||
В `WgQuickConfig` вставляется **ровно тот же текст**, что и в обычном клиентском конфиге WireGuard, например:
|
||
|
||
```ini
|
||
[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 на домашнем Wi‑Fi** — правило с `Action = Disconnect` и условием по Wi‑Fi:
|
||
- `InterfaceTypeMatch` = `WiFi`;
|
||
- `SSIDMatch` = массив SSID (например `["HomeWiFi"]` или `["Netcraze-1882"]`).
|
||
- Итог: если устройство в Wi‑Fi с этим SSID → VPN отключается.
|
||
|
||
2. **Во всех остальных случаях — подключать** — правило без условий:
|
||
- `Action` = `Connect`.
|
||
- Итог: любой другой сеть (другой Wi‑Fi, сотовые данные) → VPN включается.
|
||
|
||
Пример в plist:
|
||
|
||
```xml
|
||
<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
|
||
<?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):
|
||
|
||
```bash
|
||
# Приватный ключ
|
||
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](../containers/container-109.md).
|
||
|
||
---
|
||
|
||
## Безопасность
|
||
|
||
- В `.mobileconfig` попадают **приватные ключи** клиента. Файл нужно хранить только на доверенных носителях и не коммитить в публичный репозиторий.
|
||
- В этом проекте файлы `*.mobileconfig` и конкретно `wireguard-macos-ondemand.mobileconfig`, `wireguard-ios-ondemand.mobileconfig` добавлены в `.gitignore`.
|
||
- Передавать профиль на устройство по защищённому каналу (AirDrop, личная почта, зашифрованный диск).
|
||
|
||
---
|
||
|
||
## Установка профиля
|
||
|
||
- **macOS:** двойной клик по `.mobileconfig` → откроются «Системные настройки» → «Профили» → установить. Туннель появится в приложении WireGuard; при необходимости один раз включите его вручную, далее On-Demand будет управлять подключением.
|
||
- **iOS:** отправить файл на устройство (AirDrop, почта, «Файлы») → открыть → «Установить» → при необходимости «Настройки» → «Основные» → «VPN и управление устройством» → установить профиль. Туннель появится в WireGuard; включите один раз вручную, затем работает On-Demand.
|
||
|
||
После смены SSID или ключей — удалить старый профиль и установить новый.
|
||
|
||
---
|
||
|
||
## Связь с другими документами
|
||
|
||
- [Контейнер 109 (WireGuard)](../containers/container-109.md) — настройка сервера, ключи, клиентские конфиги, раздел «On-Demand для iOS/macOS».
|
||
- [Архитектура](../architecture/architecture.md) — таблица контейнеров, CT 109.
|
||
- [Схема сети](network-topology.md) — место VPN в топологии, доступ к vault.katykhin.ru.
|