Route raw IP packets to NEPacketTunnel's physical interface

I'm working on packet capture on iOS device with NEPacketTunnel while trying to keep the network functioning without a proxy server.

I hava viewed this thread:https://forums.developer.apple.com/message/218085#218085

Now I'm wondering how the packets to VPNServer is not looped when NEIPv4Settings.default routing all packets to vtun ?

I see that

  • Traffic destined to a local network
  • Traffic whose source address is bound to a specific interface

will not go via the route.

So that mean's the NEPacketTunnel encapsulated packets(or flow) has a source address bounded to a specific interface?

If so , is it possible to route raw IP packets (accessed with packetFlow.readPackets) to this specific interface to forward the traffic from the vTunto the original dest IP ? So that network is well functioning without proxy server and I have all packets captured?

Replies

I'm working on packet capture on iOS device with NEPacketTunnel while trying to keep the network functioning without a proxy server.

Just to be clear, I don’t think is possible as things currently stand. I had a long conversation about this with another developer (on the thread you already found). I’ll let them respond to your inquiry directly but IIRC it didn’t end successfully.

There’s a couple of ways you can force traffic to run over a specific interface:

  • Network Extension providers can create TCP connections (and UDP sessions) in two ways:

    • -createTCPConnectionToEndpoint:enableTLS:TLSParameters:delegate:
      will run the traffic directly
    • -createTCPConnectionThroughTunnelToEndpoint:enableTLS:TLSParameters:delegate:
      will run the traffic through the tunnel
  • General code can bind a socket to a specific interface (either via

    bind
    or via
    IP_BOUND_IF
    )

Another big point here is sending raw IP packets. That requires privilege escalation, and thus isn’t possible on iOS.

Share and Enjoy

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

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

I understand what you mean and my tutor has give up on this idea . But I'm sorry that I has some more questions:


1、Is iOS system keeps a IP stack that keeps IP packets outbound and inbound both inside it ? I mean, are packets from packetFlow.write write to this IP stack and system process them later?


2、If all outbound packets and inbound packets are stored in same IP stack , so system process them like this : packets with destination IP in includedRoutes go via the tunnel and the others won't go via the tunnel?


3、So if outbound packets and inbound packets are stored in same IP stack and processed in the same way , does it mean that if I manufacture a fake IP packet , which has destination IP in includedRoutes and use packetFlow.write to write it back to vtun , then I will get the same IP packet from packetFlow.read?


The question 3 is a little weird but because my tutor ask me to prove this loop exists and if so he will totally change his mind to set up a proxy server .So I want to know if the principle is like in my question above.


Sorry for asking so much foundamental questions . I'm a new iOS developer and totally work on my own and there are little documents , please forgive me!

Packet routing in iOS is rather complex. It’s definitely too complex for me to explain here, and probably more complex than I understand myself )-:

One of the big changes with respect to traditional BSD TCP/IP is that iOS supports scoped routing. On a traditional BSD system, routing is entirely determined by the destination IP address. In contrast, routing on iOS also takes into account the source IP address. This is what allows iOS to keep critical system services (like push notifications) running over WWAN even though the default route has changed to Wi-Fi.

This is not, however, the only complexity. For example, per-app VPN requires the system to track the source app for packets so that they are routed down the VPN, and I’ve never looked at the details of how that works.

Honestly I don’t think your idea will work but it’s easy enough to test that for yourself.

Finally, if you want to really understand how this stuff all works, most of its innards are included in the Darwin open source project, so you can just go look at the code (-:

Share and Enjoy

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

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

It's clear that I have to set up a proxy server , thank you , and I will try to look at the Darwin code .

And is it possible to identify the packets' source app ? I mean , I want to block some apps' network connection. The list of target apps to be blocked are variable , so I have to identify packets' souce app to see whether drop it or not.

Is there an accessible table of port and corresponding thread name so I can identify the app with the source port field in IP packet ? Or there are some other ways to identify the souce app?

Thank you !

And is it possible to identify the packets' source app ?

Only in per-app VPN mode, in which case you can go from NEPacket to NEFlowMetaData via the

metadata
field, and from there to the App ID via
sourceAppSigningIdentifier
.

Share and Enjoy

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

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

Hi Quinn , I've read a little about per-app vpn and MDM server.Now I'm still confusing if it's suitable for me.

I see that per-app vpn can route specified apps' traffic to vpn tunnel . As I want to recognize the packet's souce app , and in your reply the NEPacket is mentioned so I assume it's helpful to recognize the source app on vpn client side.

My question is that how to extract the NEPacket ? In SimpleTunnel packets are read from NEPacketTunnelFlow as Data , so is it possible to get NEPacket from NEPacketTunnel's packetflow or there is another specific way ?

And if I'm not in Enterprise Development Project and no MDM related entitlements then I'm unable to get NEPacket ?

Thank you!

My question is that how to extract the NEPacket ?

There are two types of per-app VPN:

  • App proxy providers

  • Packet tunnel providers in per-app mode (where

    routingMethod
    returns
    .sourceApplication

App proxy providers can get source application information directly from the NEAppProxyFlow object (via its

metaData
property).

Packet tunnel providers in per-app mode get source application information by calling

readPacketObjects(completionHandler:)
on the NEPacketTunnelFlow.

IMPORTANT This method is different from

readPackets(completionHandler:)
. The new method was introduced in iOS 10 and macOS 10.12 to solve exactly this problem.

And if I'm not in Enterprise Development Project and no MDM related entitlements then I'm unable to get NEPacket ?

Both forms of per-app VPN require deployment via MDM, at least on iOS. This is because you need to use MDM to set the app’s

VPNUUID
attribute to match up with the
VPNUUID
of your per-app VPN configuration.

There are two exceptions to the above:

  • On macOS you can set an app’s VPNUUID via the

    com.apple.vpn.managed.appmapping
    payload; see the App-to-Per-App VPN Mapping section of the Configuration Profile Reference for details
  • When testing on iOS you can set an app’s VPNUUID via the

    NETestAppMapping
    key in your
    Info.plist
    , as discussed in the Testing Per-App VPN section of the NETunnelProviderManager class reference

Share and Enjoy

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

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