How to deal with the traffic from NEPacketTunnelProvider?

My requirement is to create a App and all the traffic from this App will be forwarded to relay servers(only implement socks5 protocol), the relay server then forward the traffic to the destination server.

I have tried the two plans below:

A. I tried the NEAppProxyProvider but it seemed to work only under MDM, MDM looks like very complex , so I gave it up. Actually this way is more appropraite for me.

B. the other way is NEPacketTunnelProvider. I have figured out a common solution, steps:

  1. config the routes for NEPacketTunnelProvider
  2. get the fd from packetFlow
  3. start a tun2socks service to forward the traffic from the fd。

Sadly the way gettting the traffic from the fd is not recommened by apple official. so the only way to deal with the traffic is handling the packets. may be steps:

  1. parse the packet
  2. modify the packet
  3. write the packet back

... it seems even more complex than plan A,Besides, we have multiple relay servers, if there is a whole request we can make sure all this request data is forwarded by a same relay server, But if there is a packet, may be god can tell which relay server it should go to.

We have implemented the same functionality in Android devices. can you help me to find out which way is better in iOS devices? I will be appreciated if you can provide more advice. Thanks.

Answered by DTS Engineer in 796094022
My requirement is to create a App and all the traffic from this App will be forwarded to relay servers

The easiest solution here would be to upgrade your relay servers to support a more modern protocol, and then configure the device to use that relay using NERelayManager. That gets you completely out of the business of writing an NE provider, which I’m sure will be a relief. For more on this, see WWDC 2023 Session 10002 Ready, set, relay: Protect app traffic with network relays.

I tried the NEAppProxyProvider but it seemed to work only under MDM

On iOS, yes. TN3134 Network Extension provider deployment has a bunch of details about which type of providers are supported where.

2. get the fd from packetFlow

Do not do this. There’s no supported API to get a file descriptor from a packet flow and for good reason: There’s no guarantee that the packet flow contains a file descriptor. You can, for example, imagine a world when our user-space networking stack forwards packets to your packet tunnel provider directly, via shared memory or XPC, rather than through the kernel via a file descriptor.

Ultimately this issue boils down to how to take a sequence of IP packets and split them out into TCP and UDP flows, and vice versa. The third-party library you mentioned does that internally, it just expects to read and write the IP packets using a file descriptor. The library is open source, so you could:

  1. Change the code [1] to add an abstraction layer between its core and the source and sink of IP packets (assuming it doesn’t have one already).

  2. Plug-in to that abstraction layer to read and write IP packets using the packet flow.

Alternatively, you could find similar code that performs the same task. The marketing blurb for that library says “powered by gVisor TCP/IP stack”, which makes sense, because the core functionality I outlined above is exactly what a TCP/IP stack does. You could look for another library that doe similar things but are better suited to your setup [2]. For example, I’ve seen folks do this with lwIP, but I’m sure there are lots of other options out there.

Share and Enjoy

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

[1] Assuming that your work environment is compatible with its licence, of course.

[2] That is, a library with a compatible licence and that’s written in a language that’s easy to integrate with your setup.

My requirement is to create a App and all the traffic from this App will be forwarded to relay servers

The easiest solution here would be to upgrade your relay servers to support a more modern protocol, and then configure the device to use that relay using NERelayManager. That gets you completely out of the business of writing an NE provider, which I’m sure will be a relief. For more on this, see WWDC 2023 Session 10002 Ready, set, relay: Protect app traffic with network relays.

I tried the NEAppProxyProvider but it seemed to work only under MDM

On iOS, yes. TN3134 Network Extension provider deployment has a bunch of details about which type of providers are supported where.

2. get the fd from packetFlow

Do not do this. There’s no supported API to get a file descriptor from a packet flow and for good reason: There’s no guarantee that the packet flow contains a file descriptor. You can, for example, imagine a world when our user-space networking stack forwards packets to your packet tunnel provider directly, via shared memory or XPC, rather than through the kernel via a file descriptor.

Ultimately this issue boils down to how to take a sequence of IP packets and split them out into TCP and UDP flows, and vice versa. The third-party library you mentioned does that internally, it just expects to read and write the IP packets using a file descriptor. The library is open source, so you could:

  1. Change the code [1] to add an abstraction layer between its core and the source and sink of IP packets (assuming it doesn’t have one already).

  2. Plug-in to that abstraction layer to read and write IP packets using the packet flow.

Alternatively, you could find similar code that performs the same task. The marketing blurb for that library says “powered by gVisor TCP/IP stack”, which makes sense, because the core functionality I outlined above is exactly what a TCP/IP stack does. You could look for another library that doe similar things but are better suited to your setup [2]. For example, I’ve seen folks do this with lwIP, but I’m sure there are lots of other options out there.

Share and Enjoy

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

[1] Assuming that your work environment is compatible with its licence, of course.

[2] That is, a library with a compatible licence and that’s written in a language that’s easy to integrate with your setup.

How to deal with the traffic from NEPacketTunnelProvider?
 
 
Q