Post not yet marked as solved
Post marked as unsolved with 3 replies, 503 views
Hello everyone.
I made a minimal example with DNS proxy. It works well on iOS 12, and doesn't work on iOS 14 (proxy runs well, but websites don't load). Traffic on iOS 14: 2 DNS queries (type A and type 65) + 2 successful DNS responses and it's all (there are no more IP packets). DoH / DoT are disabled. In logs everything is OK (no errors, everywhere are the same number of packets (read from NEAppProxyUDPFlow = sent to NWConnection = received from NWConnection = written to NEAppProxyUDPFlow). There are no TCP connections.
Thanks in advance for any ideas / suggestions.
import NetworkExtension
//import DNS
class DNSProxyProvider: NEDNSProxyProvider {
override init() {
super.init()
}
override func startProxy(options: [String: Any]? = nil,
completionHandler: @escaping (Error?) -> Void) {
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason,
completionHandler: @escaping () -> Void) {
completionHandler()
}
override func sleep(completionHandler: @escaping () -> Void) {
completionHandler()
}
override func wake() {}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
if let tcpFlow = flow as? NEAppProxyTCPFlow {
NSLog("MyDebug: TCP connection")
} else if let udpFlow = flow as? NEAppProxyUDPFlow {
NSLog("MyDebug: UDP connection")
establishConnection(flow: udpFlow)
openFlow(flow: udpFlow)
}
return true
}
private func openFlow(flow: NEAppProxyUDPFlow) {
flow.open(withLocalEndpoint: nil) { opnErr in
if let e = opnErr {
NSLog("MyDebug: open error - \(e.localizedDescription)")
} else {
NSLog("MyDebug: open - ok")
}
}
}
private func establishConnection(flow: NEAppProxyUDPFlow) {
let conn = NWConnection(host: "8.8.8.8", port: 53, using: .udp)
conn.stateUpdateHandler = { state in
switch state {
case .ready:
NSLog("MyDebug: establishConnection ready")
self.send(flow: flow, connection: conn)
case .setup:
NSLog("MyDebug: establishConnection setup")
case .cancelled:
NSLog("MyDebug: establishConnection cancelled")
case .preparing:
NSLog("MyDebug: establishConnection preparing")
default:
NSLog("MyDebug: establishConnection default")
}
}
conn.start(queue: .global())
}
private func send(flow: NEAppProxyUDPFlow,
connection conn: NWConnection) {
flow.readDatagrams { (datagrams, endpoints, rdErr) in
let datas = self.extractReadData(rdErr: rdErr, datagrams: datagrams)
for packet in datas {
conn.send(content: packet,
completion: .contentProcessed( { sndErr in
if let e = sndErr {
NSLog("MyDebug: send error - \(e.localizedDescription)")
} else {
NSLog("MyDebug: send - ok")
self.receive(flow: flow, connection: conn)
}
}))
}
}
}
private func extractReadData(rdErr: Error?,
datagrams: [Data]?) -> [Data] {
if rdErr == nil, let datas = datagrams, !datas.isEmpty {
NSLog("MyDebug: read - ok")
return datas
} else {
if let e = rdErr {
NSLog("MyDebug: read error - \(e.localizedDescription)")
} else {
NSLog("MyDebug: read - datagrams is empty or null")
}
return []
}
}
private func receive(flow: NEAppProxyUDPFlow,
connection conn: NWConnection) {
conn.receiveMessage { (data, context, isComplete, rcvErr) in
let d = self.extractReceivedData(data: data, isComplete: isComplete, rcvErr: rcvErr)
flow.writeDatagrams([d], sentBy: [flow.localEndpoint!]) { wrtErr in
if let e = wrtErr {
NSLog("MyDebug: write error - \(e.localizedDescription)")
} else {
NSLog("MyDebug: write - ok")
}
}
}
}
private func extractReceivedData(data: Data?,
isComplete: Bool,
rcvErr: NWError?) -> Data {
if isComplete, rcvErr == nil, let d = data {
NSLog("MyDebug: receive - ok")
return d
} else {
if let e = rcvErr {
NSLog("MyDebug: receive error - \(e.localizedDescription)")
} else {
NSLog("MyDebug: receive - isComplete = \(isComplete); data = \(data)")
}
return Data()
}
}
}