iosvpnnetworkextension

iOS network extension packet parsing


I am developing a VPN (iOS Network Extension), and using C/C++ to read file-descriptor directly (instead of Swift), currently it successfully captures device's request Packets, but I don't know how to parse iOS's packets, I could not even find what network layer or protocol the packets are formatted in.

I converted Packet's binary into Hex to be able to decode with online tools; below are samples of what I need to parse:

000000024500003B5461000040110C390A07000208080808FA2D0035002739B4DE790100000100000000000003777777056170706C6503636F6D0000010001

000000024500003CBAE200004011A5B60A07000208080808E48A0035002892DAE43B01000001000000000000037777770669636C6F756403636F6D0000010001

00000002450000375324000040110D7A0A07000208080808DD7F003500232BBA841801000001000000000000056170706C6503636F6D0000010001

But when tried parsing with online decoder, they fail saying invalid packet.

What network layer or protocol is above?

Note that above are 3 packet samples (not one splitted by me).


Solution

  • It's tun-layer protocol with 4 bytes prefix:

    1. Once we use C/C++ to read file-descriptor, in NEPacketTunnelProvider like:

    let tunFd = self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32
    
    // ... pass above to C/C++ backend
    

    Instead of using Swift like:

    self.packetFlow.readPackets { [weak self] (packets: [Data], protocols: [NSNumber]) in
        // Handle packets here...
    }
    

    2. There are 4 additional bytes prefixed to the tun-layer packet (e.g. 00 00 00 02), each time we read packets.

    3. To allow most online-tools to understand the packet, remove those starting 4 bytes, and instead prefix it with Mac-Header-Hex like:

    01 00 5E 00 00 09 C2 01 17 23 00 00 08 00
    

    Note that by doing above, we convert initial tun-layer packet to a tap-layer packet.

    Also, remember to prefix again those 4 bytes, once writing a packet into the file-descriptor (after removing Mac-Header).


    Update 2021; Apple discourages accessing file-descriptor directly (and it may be removed in future iOS releases).