Packet Tunnel Provider - sleep

I've implemented a VPN app with Packet Tunnel Provider for MacOS and iOS.

I have two questions regarding the Extension's sleep/wake functions:


1. If the VPN configuration is set with disconnectOnSleep = false, and at the extension I'm sending keep-alives every X seconds,

What would happen when the device enters sleep mode? Will it keep sending keep-alive (because the VPN is configured with disconnectOnSleep=false) ?


2. If the VPN configuration is set with disconnectOnSleep = true, and also isOnDemandEnabled = true.

When the device enters sleep mode, do I need to disconnect the VPN myself? Or the OS would take care of it?

And if I should disconnect it myself, the on-demand won't try to turn it on again (because the on-demand) ?


Answered by DTS Engineer in 291454022

I recently investigated the interaction between VPN and sleep as part of a DTS incident. I’ve included the resulting info below. I think that’ll answer a bunch of your questions. If there’s any remaining, please post back with the specifics.

Your tunnel provider can work in one of two modes:

  • If

    disconnectOnSleep
    is set (
    <NetworkExtension/NEVPNProtocol.h>
    ), the system will automatically stop the tunnel as the device goes to sleep. In that case the tunnel won’t automatically start again on wake (unless triggered by an on demand rule).
  • If

    disconnectOnSleep
    is false, the system does not automatically stop the tunnel on sleep. In that case:
    • Your provider should override the

      -sleepWithCompletionHandler:
      and
      -wake
      methods (
      <NetworkExtension/NEProvider.h>
      ).
    • In the ‘sleep’ override it should quiesce the tunnel as appropriate for your protocol. In the ‘wake’ override it should reactivate the tunnel.

    • If the reactivation fails (for example, because the network environment changed in a way that prevents reactivation) your provider should stop the tunnel by calling one of the ‘cancel’ methods (for example,

      -cancelTunnelWithError
      for a packet tunnel provider).
    • Between the tunnel quiesce and reactivate your provider should set

      reasserting
      to true (
      <NetworkExtension/NETunnelProvider.h>
      ) so that the system knows it’s not connected.
    • While reactivating you can choose to clear out your tunnel settings by calling

      -setTunnelNetworkSettings:completionHandler:
      with nil for the
      tunnelNetworkSettings
      parameter (
      <NetworkExtension/NETunnelProvider.h>
      ). Doing this will stop traffic flowing into the tunnel, which might be a nice thing to do for the user if the reactivation takes a long time.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

I recently investigated the interaction between VPN and sleep as part of a DTS incident. I’ve included the resulting info below. I think that’ll answer a bunch of your questions. If there’s any remaining, please post back with the specifics.

Your tunnel provider can work in one of two modes:

  • If

    disconnectOnSleep
    is set (
    <NetworkExtension/NEVPNProtocol.h>
    ), the system will automatically stop the tunnel as the device goes to sleep. In that case the tunnel won’t automatically start again on wake (unless triggered by an on demand rule).
  • If

    disconnectOnSleep
    is false, the system does not automatically stop the tunnel on sleep. In that case:
    • Your provider should override the

      -sleepWithCompletionHandler:
      and
      -wake
      methods (
      <NetworkExtension/NEProvider.h>
      ).
    • In the ‘sleep’ override it should quiesce the tunnel as appropriate for your protocol. In the ‘wake’ override it should reactivate the tunnel.

    • If the reactivation fails (for example, because the network environment changed in a way that prevents reactivation) your provider should stop the tunnel by calling one of the ‘cancel’ methods (for example,

      -cancelTunnelWithError
      for a packet tunnel provider).
    • Between the tunnel quiesce and reactivate your provider should set

      reasserting
      to true (
      <NetworkExtension/NETunnelProvider.h>
      ) so that the system knows it’s not connected.
    • While reactivating you can choose to clear out your tunnel settings by calling

      -setTunnelNetworkSettings:completionHandler:
      with nil for the
      tunnelNetworkSettings
      parameter (
      <NetworkExtension/NETunnelProvider.h>
      ). Doing this will stop traffic flowing into the tunnel, which might be a nice thing to do for the user if the reactivation takes a long time.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks, no more questions 🙂

4 years later..

disconnectOnSleep is set:

disconnectOnSleep = true

And I have the following on-demand rule (to always connect when there's traffic):

tunnelProviderManager.isOnDemandEnabled = true
let onDemandRuleConnect = NEOnDemandRuleConnect()
tunnelProviderManager.onDemandRules = [onDemandRuleConnect]

This causes a problem on sleep -

  • When the Mac is about to enter sleep
  • stopTunnelWithReason is called (by OS) and VPN stops
  • some other app has outgoing traffic
  • the on-demand rule is matched, and the OS calls to startTunnel() //BUG here
  • Mac enter sleeps, but the VPN is still 'enabled'

There's no reason for the OS to restart the VPN if it's going to enter sleep mode. It should ignore on-demand rules in such cases.

Any way to workaround this problem (and keep the 'disconnectOnSleep = true')?

Hi @roee84. Let me know please if we can talk about my question. Thanks. https://developer.apple.com/forums/thread/684621

Packet Tunnel Provider - sleep
 
 
Q