Packet Level Filtering on MacOS

Hello! I would like to ask the community here if there is a solution or alternative approach to what I am trying to achieve as I will described below.


My goal is to achieve packet level filtering on Mac using existing architecture that my team has already developed at the company I work for.


A bit of background:

What we have achieved in Windows (full packet filtering) I would like to carry over to Mac using our existing filtering architecture. On Windows I have created a packet redirector (C++) that intercepts packets from all applications (using WinDivert) and forwards them to a modified SOCKS5 server (Java) that does the filtering. Yes, WinDivert also intercepts packets from the SOCKS5 server on their final leg out to a remote machine but I have solved that problem. The SOCKS5 server (modified for verdict filtering) is the common component which we wish to also use on Mac in addition to Windows. The only components that are platform specific are the packet redirectors.


What I have currently developed for Mac:

Basically, exactly the same as Windows mentioned above but, using NEPacketTunnelProvider instead of WinDivert. I was able to carry over all of my C++ code to Mac from Windows for the packet redirector with minimal modification and it works fine, to a point...


My problem:

As others have discovered...

https://forums.developer.apple.com/thread/74464

https://forums.developer.apple.com/thread/74194

... the PacketTunnelProvider was not designed to send packets to arbitrary destination IP addresses. It was only designed to send packets to one remote tunnel server.

To summarise; the NEPacketTunnelProvider is reintercepting its own packets. The links above explain why. This only happens when I set net.inet.ip.forwarding=1. When net.inet.ip.forwarding=0 the packets don't enter into a loop but the packets still don't reach the physical interface and consequently never reaches the remote machine. This is the pain point.

To me it seems this is a dead-end approach unless someone here has some ideas. Alternative approaches are also welcome and I have the feeling someone will mention Content Filter Providers (https://developer.apple.com/documentation/networkextension/content_filter_providers). The problem with this approach is the filter data provider is sandboxed and consequently will not be able to communicate with our separate SOCKS5 server filtering process. This basically means a re-architect of our filtering solution specially for Mac, which is highly undesirable. We want to use what we have already created.


Thanks for reading my post and I look forward to reading your replies.

Replies

There are big changes coming with regards NetworkExtension providers on macOS. Please watch WWDC 2019 Session 714 Network Extensions for the Modern Mac first, then come back with your follow-up questions.

Share and Enjoy

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

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

Hi Quinn, thanks for getting back to me.


I have watched the entire video you linked.


It still appears to be the case that the Packet Tunnel Provider is not suitable for our existing filtering architecture due to the inability to send packets to multiple destination IP addresses and the fact that it was never intended to be used in the way I described.


After some investigation triggered by the video you linked, perhaps the beta changes to the Content Filter Provider might have opened an avenue for me to explore. An avenue that might allow me to use our existing filtering architecture.


I'll be referring to NEFilterProviderConfiguration

https://developer.apple.com/documentation/networkextension/nefilterproviderconfiguration?changes=latest_minor


I am interested in two members of said class named "filterPackets" and "serverAddress". My idea is to set filterPackets to true and serverAddress to the local IP address where the SOCKS5 server filtering process lives.


Questions:


1) Looking back to how our filtering architecture works (my first post), does this approach have any chance of working?


2) The demo code for the video you posted is for socket filtering. I'm interested in packet filtering. Is there any sample code for packet filtering? Or another way to ask this question is what do I need to change in that code to use packet filtering?


3) I see there are NEFilterBrowserFlow(deprecated) and NEFilterSocketFlow classes but not NEFilterPacketFlow. What's the equivalent for packet flow? Perhaps I'm just missing something.


Thanks for your help.

A filter provider can only allow or block a flow. If you want to modify a flow — for example, to redirect it to a local proxy — you’ll need to use a transparent proxy.

Share and Enjoy

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

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

1 Re: Lose Routing with NEPacketTunnelProvider NEPacketTunnelProvider only do packet level job, but you can use lwip user-sapce stack transform to tcp connection

2 NEAppProxyProvider can forward tcp/udp stream to remote server . in your server ,you can select accept/drop.

While both of these are true, VPN providers are still not appropriate for this task. One fundamental precept of VPN is that the user wants the features provided by the VPN, and so they’ll work to keep it enabled. That’s not true when filtering, where in many cases the user doesn’t want this feature (for example, in schools or enterprise environments). If you attempt to use VPN as a filter then you also have to take steps to prevent the user from disabling your VPN, and that doesn’t end well.

In contrast, both content filters and transparent proxy must be configured by an admin user [1].

Share and Enjoy

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

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

[1] On macOS. On iOS:

  • Proxy isn’t supported.
  • Content filter only supports supervised devices, and are controlled by the device admin.