Zion Boggan zionboggan.com ↗
79 lines · markdown
History for this file →
1
# mullvad-ios-killswitch
2
 
3
Generate iOS `.mobileconfig` configuration profiles from WireGuard `.conf` files
4
with a **true kill switch** and OnDemand auto-connect baked in.
5
 
6
## Why this exists
7
 
8
The WireGuard iOS app's UI does not expose:
9
 
10
- `IncludeAllNetworks` (the toggle that makes the tunnel claim the entire
11
  default route at the iOS Network Extension level, so traffic outside the
12
  tunnel is blocked when the tunnel is down).
13
- `OnDemandEnabled` with an unconditional Connect rule (the toggle that makes
14
  iOS auto-establish the tunnel any time the device has a network).
15
 
16
Both are gated behind Apple's MDM / configuration-profile path. Once you
17
install a `.mobileconfig` that turns those keys on, the WireGuard app picks up
18
the profile as a managed tunnel and the kill switch is enforced by iOS, not
19
by the app. If the tunnel drops, the device does not fall back to the bare
20
LTE / Wi-Fi route - traffic stops until the tunnel comes back.
21
 
22
This script takes a regular WireGuard `.conf` you already have (downloaded
23
from Mullvad, your own server, anywhere) and wraps it in a properly signed-
24
shaped `.mobileconfig` with those keys flipped on.
25
 
26
## Install
27
 
28
No dependencies beyond Python 3.8+. Drop the script anywhere on your PATH.
29
 
30
## Usage
31
 
32
Single config:
33
 
34
```bash
35
python gen_mobileconfig.py \
36
  my-tunnel.conf my-tunnel.mobileconfig \
37
  --name "Mullvad Atlanta (iPhone)" \
38
  --org "Personal Setup"
39
```
40
 
41
Batch a folder of configs (one `.mobileconfig` per `.conf`):
42
 
43
```bash
44
python gen_mobileconfig.py --batch ./wg-configs ./mobileconfigs
45
```
46
 
47
AirDrop or email the resulting `.mobileconfig` to the iOS device. Open the
48
file from the Files / Mail / Messages app, accept the profile prompt in
49
Settings, then open the WireGuard app once and confirm the tunnel is
50
present and toggled on.
51
 
52
## Verification
53
 
54
After installing on iOS:
55
 
56
1. Open WireGuard, confirm the tunnel is on.
57
2. Settings -> General -> VPN & Device Management -> tap the profile,
58
   confirm "Connect On Demand" is on.
59
3. Toggle WireGuard off for a moment in the app. Try to load any page.
60
   It should fail. Toggle back on, traffic resumes.
61
 
62
If step 3 still loads pages while the tunnel is off, the kill switch is not
63
active and the profile did not install correctly.
64
 
65
## What the script does NOT do
66
 
67
- Generate your WireGuard keys. Bring your own `.conf`.
68
- Sign the `.mobileconfig` with an Apple developer certificate. iOS will
69
  warn that the profile is unsigned. That is fine for personal use - you
70
  install it manually. For a fleet deployment you should sign with `openssl
71
  smime` or push it through MDM.
72
- Validate the upstream `.conf`. If the file does not have an `Endpoint`
73
  line, the script writes an empty `RemoteAddress` (iOS will tolerate this
74
  because `WgQuickConfig` carries the real endpoint, but it is uglier in
75
  the VPN settings).
76
 
77
## License
78
 
79
MIT. See [LICENSE](LICENSE).