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?