Split VPN by protocol using Packet Tunnel Provider on iOS

We are exploring options to perform DNS lookup on iPhones, using the Packet Tunnel Provider extension. (I have read this post: https://developer.apple.com/forums/thread/111062) I have been experimenting with the Packet Tunnel Provider, and haven't had much success so far. Unfortunately, the Sample that Apple provided along with 2015 WWDC is in Swift 3, and the code is now so incompatible, it creates hundreds of error messages, and also XCode can not convert Swift 3. I have looked at a third party VPN same (kean/vpn) but haven't been able to get its tunnel working. And the documentation for the Packet Tunnel Provider is thin, and in some cases, not very descriptive.

  1. Is is actually possibly to do "split VPN" by protocol? In particular, can one sniff the packets, then simply write back to packetFlow.writePacketObjects the packets one does not wish to send thru the tunnel? (I think the answer to this question is key to whether Packet Tunnel Provider can do split VPN by protocol...)

  2. I've written some code to simply log the packets coming into the tunnel. But I barely get any packets -- pretty much just a few packets that have as source IP, the network address of a range of addresses I requested the tunnel handle, such as 42...* (source is 42.0.0.0); the destination IP is an Apple IP; it seems as if this is some kind of logging or such. I have tried both capturing some well-known address ranges such as Google servers and the servers of my own company, as well as not requesting any networks at all--I don't seem to get meaningful traffic into the tunnel in either configuration.

  3. I don't know what is the purpose of the NEPacketTunnelNetworkSettings(tunnelRemoteAddress String) parameter -- if I don't pass this, the init fails, but it is in the super class of this object, and since a VPN Tunnel must provide all of its own tunneling logic, it is not clear why the config needs the server address; in the sample app I have, it is set to the sample app's server address; I have been setting it to the IP address of my Mac, and also giving it a unique but non-existent IP on my local network -- neither seems to matter

  4. The sample app I have doesn't set any additional parameters of that configuration -- it doesn't set any IPv4 or IPv6 networks, doesn't set DNS lookup information, and doesn't set network packet size properties. Does an empty configuration imply the request to route ALL device traffic thru the tunnel? If this is the case, I don't understand why I don't start seeing almost any network traffic coming out of my read loop (apart from the few Apple-destined packets I mentioned.) I expected to see a flood of traffic from the tunnel, such as when browsing in Safari -- but browsing works on Safari, and the packets don't seem to get sent to the tunnel.

  5. I'm doing all the above with my phone connected by a lighting cable to my Mac, so I can log and debug -- is this somehow messing up the ability to use the tunnel?

  6. Under many configuration combinations, I do see the VPN icon on the iPhone after starting the tunnel; but as mentioned, I get no significant packet traffic into the tunnel, as shown by my logging

  7. Is there an updated sample application? The one for iOS9 is now 5 years old, and can't even be opened in the newest versions of XCode, and an old version of XCode won't even run on newer Mac OS anymore...

Thanks for any help!

Unfortunately, the Sample that Apple provided along with 2015 WWDC is in Swift 3, and the code is now so incompatible, it creates hundreds of error messages, and also XCode can not convert Swift 3. Is there an updated sample application?

I believe you are referring to SimpleTunnel. Please see this post regarding the state of this project.

Regarding:

Is is actually possibly to do "split VPN" by protocol? In particular, can one sniff the packets, then simply write back to packetFlow.writePacketObjects the packets one does not wish to send thru the tunnel?

No. If you consume the packet, you must send the packet out over the network to avoid client side networking errors.

Regarding:

I don't know what is the purpose of the NEPacketTunnelNetworkSettings(tunnelRemoteAddress String) parameter

The purpose of this parameter is to make sure that when your virtual interface is created that packets that are intended for your VPN server address do not fall into a packet loop.

Regarding:

Does an empty configuration imply the request to route ALL device traffic thru the tunnel?

No. You will need to claim 'NEIPv4Route's and 'NEIPv6Route's on your NEPacketTunnelNetworkSettings for traffic to traverse your tunnel.

Regarding:

I'm doing all the above with my phone connected by a lighting cable to my Mac, so I can log and debug -- is this somehow messing up the ability to use the tunnel?

No, that should be fine. When I debug traffic flowing through iOS packet tunnels, this is one way that I perform my debugging. Keep in mind though that using LLDB and Xcode here will provide you more flexibility for debugging and troubleshooting, which is good during the debugging and implementation stages of your project. When you have a finished project you are wanting to test in the field, make sure you run this outside of Xcode to ensure that all of the real world constraints are imposed on your tunnel such as memory limits etc..

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Split VPN by protocol using Packet Tunnel Provider on iOS
 
 
Q