Detecting Fast-User Switch with a Network System Extension

I am running into an issue with running a PacketTunnelProvider as a system extension, and fast user switching.

Since the VPN is running as root, it runs outside any user context, and is accessible to all users on the machine. I can see the following behavior:

  1. Login to User A
  2. Connect VPN
  3. Fast switch to user B
  4. Open Safari, observe that traffic is directed and sent out the VPN. (As noted by the ability to browse otherwise un-reachable websites).

Is there a way to detect that a fast user switch is happening? And disconnect the VPN when user B takes control of the screen.

I know NSWorkspace is not a daemon-safe API. So NSWorkspaceSessionDidResignActiveNotification and like will not be useful here.

One alternative would be to use NSWorkspace notifications in the GUI and alert the system extension via XPC. But that wouldn't work in the case where there isn't a GUI, such as with ConnectOnDemand.

Is there a daemon-safe API to use or some other alternative?

Thanks

Replies

If you care about the user context, it’s best to ship your VPN as an appex rather than an sysex. See TN3134 Network Extension provider deployment for more about that.

Having said that, I suspect that your problem is architecturally unsolvable. You wrote:

Is there a way to detect that a fast user switch is happening?

Why are you trying to do that? Packet tunnel providers operate at the bottom of the networking stack, so the virtual interface they create is open to all. As a packet tunnel provider, you can’t assume that, because user A is logged in, traffic from apps is coming from user A. There are numerous cases where that’s not true:

  • Fast User Switching, as you’re discussing here — Note that, in the Fast User Switching case, the original user keeps running, so you might get app traffic from multiple users.

  • Multiple GUI using, via screen sharing — In this case you can have multiple users running on the GUI simultaneously.

  • Background work — Background operations may be happening on behalf of a user B while user A is logged in.

You might be better off using a different type of provider [1], or deploy your packet tunnel provider in per-app VPN mode.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] In DTS we regularly see folks attempting ‘off label’ use of a packet tunnel provider, to the point that one of my colleagues wrote TN3120 Expected use cases for Network Extension packet tunnel providers. However, that’s usually on iOS, where the other provider types have significant limitations. macOS has much fewer limitations for NE providers.

Why are you trying to do that?

Hi @eskimo, we are doing this so that we can ship outside of the app store.

we are doing this so that we can ship outside of the app store.

OK. That means building a system extension, so you have to decide how you want to handle the various cases I described. For example, do you want to tear down your tunnel just because a second user logged into the Mac via screen sharing?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"