Managing and switching multiple NEPacketTunnelProvider

I have an iOS app (let's call this "APP A") that correctly installs and uses a VPN profile with NEPacketTunnelProvider.

I see this profile in settings ("PROFILE A"), and it is correctly used every time network is requested, because I configured it to do so.

This VPN needs to be always running, per company requirement. If I switch it off in settings, it gets automatically rearmed because of this rule.


let connectRule = NEOnDemandRuleConnect()
            manager.onDemandRules = [connectRule]
            manager.isOnDemandEnabled = true


I have another app ("APP B") in the same app group (we manage both of them). APP B has its own VPN profile with NEPacketTunnelProvider ("PROFILE B"), and I see it in settings.

This PROFILE B VPN is only for foreground use, as is started at APP B launch and closed when we switch away (there are some watchdogs, etc). This is by design, and it's ok that it overrules PROFILE A only when using APP B.


When I have PROFILE A active, all works well. It manages all requests and gets reactivated if I switch it off in settings.

When I launch APP B, PROFILE B is correctly selected, activated and used.

But when I return to home/switch away from APP B, PROFILE B deactivates correctly, but profile A never gets activated automatically. Looks like the last - the one with the ✓ in settings - have the precedence now; in this case, it is PROFILE B.

If I switch PROFILE A on by hand in settings, it works of course.


Is there any way to go back to PROFILE A after I close APP B?

I was thinking that being in the same app group could help, but I can't find a way to do it.


I could try to move both profiles to APP B, that will then manage the switching, but I'm not sure if this could be a solution. Apart from this, I would prefer not having even more stuff in APP B, that is mission-critical and with a lot of things going (security, etc.)


Any idea on how I could manage the transition in the best way?

Is there some way to let an app programmatically switch to a profile of another app (same group)?


PS: I was also thinking about using background modes for checking the status (for example Background App Refresh or the new BackgroundTasks), but I think these don't have precise timings, so I will have some time when no VPN will be active.

Replies

I suspect that this actually may be working as designed. When network traffic is active again, does Profile A activate? You most likely are in a state where the system is deciding which profile should be the provider for the network flow. Once traffic on your device starts again, do you see one of the profiles kick on?


| Is there any way to go back to PROFILE A after I close APP B?

| I was thinking that being in the same app group could help, but I can't find a way to do it.


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

When network traffic is active again, it does not switch from Profile B (activated due to app b launch) to Profile A, but stays with the latest activated one (B). And given that profile B is not on demand, no profile gets activated at all. I only see in settings the ✓ in profile B, but it is disconnected.


Do you think there could be a workaround?


Thanks a lot


PS: sorry for the late reply, there was notification disabled for this account 😅

Is Profile B a Per-App VPN? This could be one option to investigate if the switch back to Profile A is not taking place when there is network activity. The reasoning here would be that Profile B is only active in the foreground for a specific app, all other times Profile A's on-demand rules should fulfill the traffic.


I would have to dig into this further to see if something is preventing the transition from taking place back to Profile A or if this profile is just in a limbo state while the VPN re-connects. You can open a DTS incident and I can take a look into this time window further with a sysdiagnose.


You did mention, "If I switch PROFILE A on by hand in settings, it works of course," so triggering this by hand works does work at the moment.

| Do you think there could be a workaround?



Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Is Profile B a Per-App VPN? This could be one option to investigate if the switch back to Profile A is not taking place when there is network activity. The reasoning here would be that Profile B is only active in the foreground for a specific app, all other times Profile A's on-demand rules should fulfill the traffic.


Profile B is a regular one, especially because we're not under MDM management. It is deactivated when APP B goes to background, but it's a regular OpenVPN profile.


You did mention, "If I switch PROFILE A on by hand in settings, it works of course," so triggering this by hand works does work at the moment.

Triggering by hands in settings works. Triggering when launching APP A works. The only problem is when it's selected another profile, and after that VPN disconnets, it don't switch back to PROFILE A.


Soon I'll open a DTS, but any help would be great in the meantime. Thanks a lot for your great support.


Klaus

Klaus,


I see. Based on the what you have described it sounds like your onDemandRules for profile A are not being activated consistently. This would be the first thing I would dig into.


Next, I would also attempt to verify each flow of traffic for each VPN. This will help you debug this problem. It will also allow you to detect when the system has handed over the network traffic to a VPN to handle the flow.

| Profile B is a regular one, especially because we're not under MDM management. It is

| deactivated when APP B goes to background

|

| When network traffic is active again, it does not switch from Profile B (activated due

| to app b launch) to Profile A, but stays with the latest activated one (B).



Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Hi Matt,

your insights put me on the right track! Looks like i found a way!


I changed the VPN configuration for APP B, making it `isOnDemandEnabled = true` too.

I have added the logic in APP B to set it's PROFILE B to disabled everytime I exit the app. When it gets disabled, the on demand part is taken from PROFILE A, so this is good.


Now for the fun part... This logic works only if the name in VPN setting for PROFILE A is in alphabetical order before the one for PROFILE B (or any other one also)!!!

This looks like a bug to me, there should be some assurance on which on demand profile would get activated when the current one is disabled, other than an alphabetical order, right? Thought that the previously selected one would be a good choice maybe...

Otherwise this will mean that a profile named for example "AAAAAAAVPN Profile" will quite always take precedence on other ones.


Do you have any insight on what should be the correct behaviour in this case?

Klaus,


Excellent. Glad to help.

| your insights put me on the right track! Looks like i found a way!


As far as what you are seeing, I'm not sure this is a bug. This may be due to activation order of these profiles as well. This could also be the result of network and environment conditions being met that result in this behavior. My recommendation would be to keep digging into these conditions as you debug this sequence.


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Everything was working fine and great, but now it looks that with iOS 13.5 the extension gets killed continuously because of memory pressure.

Before the update I was seeing 7-10 MB max, now it's in starting the same, but then a spike of 15 MB kills it. Code is the same.


Do you know if there is something new regarding this with the latest 13.5 release?


Thanks