Sending UDP packets over both Wi-Fi & Cellular (LTE) within Packet Tunnel Provider

I am developing a VPN app for bonding both Wi-Fi & Cellular connections, and try to figure out how to create two UDP sockets within Packet Tunnel provider and bind them to Wi-Fi and Cellular interfaces respectively. Any help/suggestion is greatly appreciated.

I am developing a VPN app for bonding both Wi-Fi & Cellular connections, and try to figure out how to create two UDP sockets within Packet Tunnel provider and bind them to Wi-Fi and Cellular interfaces respectively.

I am assuming this is iOS, so I will recommend that you do not try and bind to the tunnel's network connection to a network interface, but rather let the device use the path that is most appropriate for the device's current conditions. Another option is to use an in-provider networking API like NWUDPSession. If you need to claim routes on your NEPacketTunnelProvider for Cellular and Wi-Fi, do so in your NEPacketTunnelNetworkSettings and make sure to claim both NEIPv4Settings and NEIPv6Settings on your virtual interface to handle IPv6 only cellular networks.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

I took a look at NEIPv4Settings. It seems for configuring the TUN interface. How can I create two NWUDPSessions, one over Wi-Fi, and the other over Cellular ? I wonder what APIs are used in this VPN app (https://apps.apple.com/us/app/speedify/id999025824#?platform=iphone) for sending traffic over both Wi-Fi and Cellular simultaneously.

Below is a related post (https://developer.apple.com/forums/thread/76711), and I am looking for the solution to the exact same problem.

////////////////////////////////////////////////////////////////// I too am trying to concurrently direct traffic out through either wifi or cellular (based on some policies/business logic similar to the OP) but running into problems.

The approaches described here (and similar others here and here) to bind a BSD socket to cellular - via bind(ip of cellular) or setsockopt(IP_BOUND_IF, cellular i/f) - work great when performed within an app but do not work when performed from within my Packet Tunnel provider. The binding itself succeeds, but then any attempts to connect on the cellular-bound socket always fail with EADDRNOTAVAIL.

I ran some additional experiments and found: The connect works perfectly fine when done from an app (instead of within my PT provider). I also tried this as a separate app while my PT provider was actively running at the same time and had no problems. I can connect() on the cellular-bound socket from within my packet tunnel provider as long as it is before I call the startTunnel completion handler (i.e. before VPN tunnel is brought up by the system). IOW, the only time the connect() fails is when I try to do it from within my PT provider and only after my tunnel is started (after I call the completion handler). The same EADDRNOTAVAIL occurs with both TCP and UDP sockets. The EADDRNOTAVAIL doesn't seem to be related to the port already being used (which is the typical cause), since I'm calling bind() with 0 for the port.

So, I'm wondering: Am I doing something wrong, i.e. is there something subtlely different that needs to be done within a PT provider that isn't typically required in an app? Is there a known issue with connecting cellular-bound sockets from within a tunnel provider? Is there some other method I can use to send some subset of my traffic over cellular, while still concurrently sending most of my traffic over wifi? I'm running a single full tunnel (not split) and finding that createTCPConnectionToEndpoint only allows me to send out over the current default network (not selectively and concurrently out either cellular or wifi when both are available).

Any help would be greatly appreciated. Thanks!

How can I create two NWUDPSessions, one over Wi-Fi, and the other over Cellular ?

I would recommend using one instance of this object provided to you by the packet tunnel provider and then letting the system delegate the path.

Regarding:

The same EADDRNOTAVAIL occurs with both TCP and UDP sockets. Is there a known issue with connecting cellular-bound sockets from within a tunnel provider?

I will recommend that you again stay away from trying to bind a BSD socket to a network interface from this context. Use a system API to handle this for you and that way you do not run into a situation where you are binding to an unavailable path. If you find that your tunnel is experiencing network latency issues, then reconfigure the settings to claim a difference route.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Sending UDP packets over both Wi-Fi & Cellular (LTE) within Packet Tunnel Provider
 
 
Q