I have a network extension setup on my app using the NEPacketTunnelProvider
Network Extension.
I have set its DNS settings like so, to override all system DNS settings:
let dnsSettings = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4"])
dnsSettings.matchDomains = [""]
tunnelNetworkSettings.dnsSettings = dnsSettings
After that, I am catching all DNS network packets (aka UDP, port 53) using
tunnelProvider.packetFlow.readPackets { ... }
When the packets are incoming, I am stripping them of their headers and sending their payload (DNS Query) to the DNS servers using
currentUDPSession.session.writeMultipleDatagrams(packetPayloadsToSend) { ... }
And receiving back the answers using the callback on NWUDPSession
currentUDPSession.session.setReadHandler { ... }
Then, on the received datagram payloads (DNS Answer) I am rebuilding the UDP headers (whether it's IPv4 or IPv6, I'm supporting both), and writing them back to the TUN interface like so:
// Examples of the data I'm passing. I'm populating it with VALID rebuilt packets beforehand
let rebuiltPackets = [Data]()
let rebuiltPacketsProtocols = [NSNumber]()
tunnelProvider.packetFlow.writePackets(rebuiltPackets, withProtocols: rebuiltPacketsProtocols)
On paper, everything looks great and sniffing those packets using Wireshark shows that everything should work. But here's the thing, It doesn't!
When trying to access any website on the iPhone I am getting:
Safari could not open the page because the server stopped responding.
Here's a screenshot of the Wireshark PCAP for trying to access twitter.com
:
IP address 10.0.0.43
is my tunnel, while 172.20.100.155
is my iPhone's local network IP address. Not sure why it shows both tunnel and OS DNS packets, but someone told me it's regular iOS behavior.
Any ideas? Thanks!