Split tunneling.

My task is to develop split tunneling feature for macOS so if I am connected to a VPN connection only selected apps can send their traffic to the VPN tunnel while other apps will be using local internet tunnel.


Apple recently announced Network Extensions and deprecated Network Kernel Extension, Network Extension provide a different set of API what specific API I should use to achieve my target ?


Thanks,

Replies

To get started with your VPN I would recommend using the NETunnelProviderManager API in your macOS application and the NEPacketTunnelProvider API in your System Extension. Routing traffic away from the VPN and through a connection to the wider internet will present a challenge though as this is not how this API was intended to work. For more information on this and what's new in Network Extensions take a look at this year's WWDC video here.


For more information on how to setup and register a System Extension in your application, take a look at the Filtering Network Traffic sample project here.


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

My task is to develop split tunneling feature for macOS so if I am connected to a VPN connection only selected apps can send their traffic to the VPN tunnel while other apps will be using local internet tunnel.

What does “local internet tunnel” mean in this context?

Also, what’s your deployment target here? Are you planning to deploy to a managed environment? Or to general users (via the Mac App Store or independent distribution)?

Share and Enjoy

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

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

Local internet tunnel means my WAN/LAN internet connection, actually I am developing a VPN client which offers split tunnelling feature which allows a user to select specific apps to use the VPN tunnel and all other (non selected apps) will be using default internet connection for out going traffic.


Yes the app is for the general users.


Thanks.

There is an application named Express VPN which offer split tunneling I am sure they are using Network Extensions for this purpose.

Local internet tunnel means my WAN/LAN internet connection

OK, thanks for clarifying that.

[FYI, labelling your default Internet connection as a “tunnel” is kinda weird. Normally we reserve the word “tunnel” for situations where you have network traffic nested within other network traffic, as is typically done by VPN.]

Yes the app is for the general users.

This is going to be a challenge. There are two basic approaches for implementing per-app VPN on the Mac:

  • Network Kernel Extensions (NKEs)

  • NetworkExtension (NE) providers

NKEs were officially deprecated in macOS 10.15, and I recommend that you avoid going down that path.

On the NE front, there are four standard ways to create per-app VPN:

  • An NE app proxy provider app extension

  • An NE packet tunnel provider app extension in per-app VPN mode

  • The system extension variants of the above

Note If you’re not familiar with how these parts fit together, I strongly encourage you to watch WWDC 2019 Session 714 Network Extensions for the Modern Mac, which is a great overview of these technologies.

The drawback to all of these is configuration. Per-app VPN is, by design, restricted for use in managed environments. On iOS the target apps must be installed via MDM. This restriction is not as tight on macOS, but there’s still no API to configure which apps run over which VPN configurations. Rather, this mapping is set up via a configuration profile using the

com.apple.vpn.managed.appmapping
payload, and that’s not a great user experience.

You may be able to make some headway using a NE transparent proxy system extension and then looking at each flow’s metadata [1] to decide whether to route it via your VPN or not. Honestly, I’m not sure whether that will work because I’m not sure whether the metadata is available in the transparent proxy case.

Share and Enjoy

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

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

[1] The

metaData
property of the
NEAppProxyFlow
class, which is the base class for both
NEAppProxyTCPFlow
and
NEAppProxyUDPFlow
.

Thanks for your reply and I really appreciate for correcting me regarding tunneling concept, okay so if I move forward with NetworkExtension instead of Network Kernel Extensions would my app compatible with older macOS versions ? as I noticed NETransparentProxyManager is only available in macOS 10.15 or newer.



Thanks.

if I move forward with NetworkExtension instead of Network Kernel Extensions would my app compatible with older macOS versions ?

That depends on which specific NetworkExtension (NE) provider you use. Some providers, like a packet tunnel provider run as an app extensions, are supported back to 10.11. Others, like a transparent proxy, require 10.15.

If you need to use one of these new NE providers, there’s no way to build a single codebase that’ll support all releases of macOS going forward:

  • Systems prior to 10.15 require an NKE.

  • 10.15 supports NKEs and the new NE providers.

  • Some future version of macOS will not support NKEs.

If you’re in that situation, I recommend that you start with an NE provider. This has a number of benefits:

  • It’s much easier than working in the kernel.

  • To deploy a KEXT widely you need a Developer ID that’s been enabled for KEXT development (see this post for details). It’ll be easier to get that if you already have an NE provider in place, and thus you only need it for backward compatibility.

  • By the time you’re done with the NE development, you may decide that it’s not necessary to support older systems.

  • It’s possible that your NE development might uncover a problem with the OS that needs to be resolve by Apple in order for your product to be successful. If that’s the case, it’s best to know about it (and file a bug, obviously) sooner rather than later.

Share and Enjoy

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

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