Hi,
We're in the process of following Apple’s guidance on transitioning away from Packet Filter (pf
) and migrating to a Network Extension-based solution that functions as a firewall. During this transition, we've encountered several limitations with the current Content Filter API and wanted to share our findings.
Our VPN client relies on firewall functionality to enforce strict adherence to split tunneling rules defined via the routing table. This ensures that no traffic leaks outside the VPN tunnel, which is critical for our users for a variety of reasons.
To enforce this, our product currently uses interface-scoped rules to block all non-VPN traffic outside the tunnel. Replicating this behavior with the Content Filter API (NEFilterDataProvider
) appears to be infeasible today.
The key limitation we've encountered is that the current Content Filter API does not expose information about the network interface associated with a flow. As a workaround, we considered using the flow’s local endpoint IP to infer the interface, but this data is not available until after returning a verdict to peek into the flow’s data—at which point the connection has already been established. This can result in connection metadata leaking outside the tunnel, which may contain sensitive information depending on the connection.
What is the recommended approach for this use case?
NEFilterPacketProvider
?
This may work, but it has a negative impact on network performance.- Using a Packet Tunnel Provider and purely relying on
enforceRoutes
?
Would this indeed ensure that no traffic can leak by targeting a specific interface or by using a second VPN extension?
And more broadly—especially if no such approach is currently feasible with the existing APIs—we're interpreting TN3165 as a signal that pf
should be considered deprecated and may not be available in the next major macOS release. Is that a reasonable interpretation?
My go-to reference for this sort of stuff is Routing your VPN network traffic [1]. This outlines two options for preventing ‘escapes’:
-
For a full tunnel, set
includeAllNetworks
and then set exceptions via the variousexcludeXYZ
options. -
For a split tunnel, set
enforceRoutes
. There’s some subtlety with this, as explained in the Enforce the inclusions and exclusions for a packet tunnel provider section.
That leaves this:
be able to block any traffic while the tunnel is not yet connected
Honestly, I’m not sure what the best path forward is for that requirement. I’m gonna research that and get back to you.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] I know you’ve seen this but I’m replying as if you haven’t so that our conversation makes sense to other folks reading this thread.