Network Protection
Kill Switch
The Kill Switch controls what happens to network traffic when the VPN connection drops unexpectedly. Configure it on
the KapeVPNManager before connecting:
vpn.killSwitchMode = .off // or .standard / .advanced
Modes
| Mode | Behaviour | When to use |
|---|---|---|
.off | If the VPN tunnel drops, traffic continues over the regular internet connection uninterrupted. | Suitable when uninterrupted connectivity matters more than privacy, e.g. during development. |
.standard | The SDK continuously attempts to reconnect. All internet traffic is blocked until the tunnel is restored. System services such as CarPlay, AirDrop, and local network communication remain functional. | Recommended default for consumer VPN apps. |
.advanced | All traffic without exception must be routed through the tunnel. Any traffic that cannot be tunnelled — including system services and local network communication — is blocked until the tunnel is restored. | High-security scenarios where any unprotected traffic is unacceptable. |
.advanced mode forces all traffic — including system services like AirDrop, push notifications, and CarPlay —
through the VPN tunnel. However, these services rely on local network communication, which is inherently unreachable
via a VPN tunnel. As a result, they will stop functioning whenever the tunnel is active or recovering. This mode
causes significant restrictions for everyday device usage and should be used only when the security requirement
explicitly demands it.
Connect on Demand
Connect on Demand lets iOS start the VPN tunnel automatically as soon as the device generates internet traffic —
without any user interaction. Enable it on the KapeVPNManager before connecting:
vpn.connectOnDemand = true
When enabled, iOS monitors outgoing connections and triggers the VPN tunnel the moment traffic is detected. The VPN stays active as long as Connect on Demand is enabled; disabling it returns to manual connect/disconnect control.
Connect on Demand is implemented via iOS NEOnDemandRule. The VPN profile must be installed (installProfile())
before this setting takes effect.
Combining Connect on Demand with Kill Switch .standard or .advanced means that after an unexpected tunnel drop,
traffic is blocked and iOS will immediately try to re-establish the tunnel automatically. This is the recommended
combination for maximum privacy.
Connect on Demand Rules
For finer control, you can define an ordered list of rules that determine when the VPN connects automatically. Rules are evaluated in order — the first matching rule wins.
vpn.onDemandRules = [
// Disconnect on a trusted home network
KapeOnDemandRule(condition: .ssid("Home WiFi"), action: .disconnect),
// Connect on any other WiFi
KapeOnDemandRule(condition: .wifi, action: .connect),
// Connect on cellular
KapeOnDemandRule(condition: .cellular, action: .connect),
]
Each KapeOnDemandRule has a condition and an action:
Conditions
| Condition | Matches |
|---|---|
.ssid("Name") | A specific WiFi network by SSID |
.wifi | Any WiFi network |
.cellular | Any cellular (mobile data) connection |
Actions
| Action | Behaviour |
|---|---|
.connect | Start the VPN tunnel automatically when this condition is met |
.disconnect | Prevent automatic connection (or disconnect if currently active) |
When onDemandRules is empty and connectOnDemand is true, iOS uses a single catch-all connect rule — equivalent
to setting connectOnDemand = true without any rules.
Rules are persisted automatically and restored on the next app launch. They take effect immediately whenever
connectOnDemand is true.
Rule order matters. Put more specific .ssid rules before broad .wifi or .cellular rules, otherwise the specific
rules will never be reached.
Split Tunneling
Split Tunneling lets you control which traffic is routed through the VPN and which bypasses it. Define rules as a list of IP ranges in CIDR notation, either as a whitelist (only matching traffic goes through the VPN) or a blacklist (matching traffic bypasses the VPN).
// Whitelist — only these ranges are routed through the VPN
vpn.splitTunnel = .whitelist([
"10.0.0.0/8",
"192.168.1.0/24"
])
// Blacklist — these ranges bypass the VPN
vpn.splitTunnel = .blacklist([
"203.0.113.0/24",
"198.51.100.0/24"
])
Domain-based rules
Instead of hardcoding IP ranges, you can provide a domain name. The SDK resolves its IP addresses automatically before the tunnel is established and applies the resolved ranges to the rule:
vpn.splitTunnel = .whitelist([
.cidr("10.0.0.0/8"),
.domain("internal.example.com")
])
IP addresses are resolved at connection time only. If a domain's DNS records change while the tunnel is active, the split tunnel rules are not updated until the next connection.