I've implemented a custom VPN for macOS (system extension, Packet Tunnel Provider, Developer ID). My tunneling logic uses BSD sockets. My VPN is configured with on-demand and should always connect when there's traffic:
targetManager?.isOnDemandEnabled = true
targetManager?.onDemandRules = [NEOnDemandRuleConnect()]
I have encountered some issues when the device enters sleep (or waking up from sleep). I've tried two scenarios.
Scenario 1:
protocolConfiguration?.disconnectOnSleep = true
With this flag set, the OS will disconnect the VPN just before entering to sleep. However, there were cases when the OS disconnected the VPN but immediately restarted it - probably because of how I defined the on-demand rules. This resulted in the VPN disconnection, then trying to reconnect, and then the Mac entered sleep. When the Mac woke up, the VPN didn't work well.
- Is there a way to avoid waking up, just before the Mac enters sleep?
Scenario 2:
protocolConfiguration?.disconnectOnSleep = false
Disconnect on sleep is unset, and I've implemented the sleep/wake functions at the provider.
With this configuration, the OS won't disconnect the VPN, so even in sleep, the extension should stay 'alive,' so it won't have the problem from (1).
But in this case, I had other problems:
-
On sleep, I'm disconnecting the tunnel. But sometimes, on wake(), all my network calls fail. Are the interfaces still down? How can I detect this case from the system extension?
-
Is it possible that the OS would call sleep and then quickly call wake?
-
Is it possible that after sleep, the OS would call the startTunnelWithOptions() function?
-
Is it possible to restart the extension from a clean state right from the wake() function?