NEPacketTunnelFlow failed to write IP packets

I'm implementing a custom VPN by using iOS9 NetworkExtension framework. The vpn connection has established between my iphone and the vpn server. But my iPhone still can't access Internet.

I did the following steps:


1. Reading IP packets from tun, and sent it to vpn server using udp:



- (void)startReadingTunPackets{
        [self.packetFlow readPacketsWithCompletionHandler:^(NSArray<NSData*> *packets, NSArray<NSNumber*> *protocols) {
        for(NSData *data in packets){
            [self.UpdSession writeDatagram:data completionHandler:^(NSError * error){
            }];
        }
        [self startReadingTunPackets];
  }];


2. The vpn server received the udp data, decoded them to ip packet (eg. a TCP SYN packet) and changed its source address to the vpn server's address. Send the fake SYN packet to remote site.



3. The remote site responded a TCP SYN/ACK packet to the vpn server.


4. The vpn server modified the SYN/ACK packet's destination address to iPhone's tun address(eg. 10.0.1.100), sent it to iPhone.



5. iPhone used the following code to receive udp data that contains SYN/ACK packet and sent them to tun:


[udpSession setReadHandler:^(NSArray<NSData *> * datagrams, NSError * error) {
      for(NSData *data in datagrams){
          NSArray *packet = [[NSArray alloc] initWithObjects:data,nil];
          NSArray *protocols = [[NSArray alloc] initWithObjects:@(AF_INET),nil];
          //Write to TUN
          BOOL r = [self.packetFlow writePackets:packet withProtocols:protocols];
          }} maxDatagrams:4096];



I thought an ACK packet can be read from tun in order to complete 'three-way handshake'. But this never happened. Instead, a SYN packet was read from tun, like TUN has never received the SYN/ACK packet, which as I described in step 5. Though, The call to packetFlow.writePackets() succeeded.


I guess something might went wrong with the packet format in step 5. Should it to be a complete ip packet or just payload? Or should I not modify the SYN/ACK's destination address in step 4?

Replies

2. The vpn server received the udp data, decoded them to ip packet (eg. a TCP SYN packet) and changed its source address to the vpn server's address.

Packet tunnels act at the IP layer, and thus shouldn’t need to modify the packets flowing through the tunnel. You should arrange for your VPN server to return an appropriate IP address to the VPN client, which then uses that as the source IP address of the tunnel. That’ll ensure that you’re packets start out with the correct source address, which makes everything easier.

Share and Enjoy

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

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

Thank a lot for your quick reply, eskimo. But I'm still confused. 😕


You should arrange for your VPN server to return an appropriate IP address to the VPN client, which then uses that as the source IP address of the tunnel.


What does that mean? Which step below is wrong?


1. The VPN client app makes VPN connection, the TUN address is assigned to : "10.0.1.100" , set TUN as default route.

2. Open Safari to access Internet (e.g. http://123.123.123.123)
3. The VPN client reads a TCP SYN packet from TUN. The packet's source address is "10.0.1.100", destination address is "123.123.123.123"

4. Encapsulates above packet into UDP data, send the UDP data to VPN server

5. VPN server receives the UDP data, decapsulates it to a TCP SYN packet.
6. Modify the TCP SYN packet's source address to VPN server's address "10.0.0.12" from "10.0.1.100"

7. Send the TCP SYN packet directly

8. VPN server receives a TCP SYN/ACK packet from remote site. the packet's source address is remote site(123.123.123.123), destination address is VPN server's address(10.0.0.12)

9. Modify the TCP SYN/ACK packet's destination address to TUN's address(10.0.1.100). Should I do that or not?

10. Encapsulates above packet into UDP data , send them to the VPN client

11. The VPN client receives UDP data, decapsulate it to a TCP SYN/ACK packet.

12. Writes above packet into TUN


I've tried to skip step 9, keep the TCP SYN/ACK packet's destination address as VPN server's address. But stil got same result.

Hi.Have you solved it?

FYI: linked from a similar posts of mine: https://forums.developer.apple.com/message/202945#202945 together with a variety of posts regarding the same issue.

I am entirely sure if anyone has managed to solve this (and didn't bother to update their question with the answer) or not, as any workaround and suggestions found on the forum does not seem to work. Happy to share the knowledge here in case that helped with moving forward.

FYI: linked from a similar posts of mine … together with a variety of posts regarding the same issue.

I don’t think these issues are related. Your issue is specifically about the VPN server that comes with the SimpleTunnel sample code. AFAICT this thread is about folks talking to their own VPN server.

Share and Enjoy

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

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