How to use NEDNSProxyProvider in iOS 11

Viewed 6053

On the networking side, DNS Proxy is one of the biggest features of iOS 11. But they haven't provided much documentation or samples regarding it. There's a talk on it as well where they have just given a description of what is possible with DNS Proxy.

I want to create a working sample of it but didn't get success till now. So I have created a Network Extension with DNS Proxy entitlements and added a DNS Proxy Provider. Here's the code:

class DNSProxyProvider: NEDNSProxyProvider {
    let defaults = UserDefaults(suiteName: "group.com.securly.dnsProxy")

    override init() {
        NSLog("QNEDNSProxy.Provider: init")
        super.init()
        // +++ might want to set up KVO on `systemDNSSettings`
    }

    override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
        NSLog("QNEDNSProxy.Provider: start")
        // self.defaults?.set("DidStart", forKey: "DidStart")
        completionHandler(nil)
    }

    override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
        NSLog("QNEDNSProxy.Provider: stop")
        completionHandler()
    }

    override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
        NSLog("QNEDNSProxy.Provider: new flow (denied)")
        // self.defaults?.set("DidHandleNewFlow", forKey: "DidHandleNewFlow")
        return true
    }

}

Then in AppDelegate, I declare a NEDNSProxyManager and use it as:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let manager = NEDNSProxyManager.shared()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        self.enable()
        return true
    }

    private func enable() {
        self.update {
            self.manager.localizedDescription = "DNSProxySample"
            let proto = NEDNSProxyProviderProtocol()
            // proto.providerConfiguration = +++
            proto.providerBundleIdentifier = "com.securly.dnsProxy"
            self.manager.providerProtocol = proto
            self.manager.isEnabled = true
        }
    }

    private func disable() {
        self.update {
            self.manager.isEnabled = false
        }
    }

    private func update(_ body: @escaping () -> Void) {
        self.manager.loadFromPreferences { (error) in
            guard error == nil else {
                NSLog("DNSProxySample.App: load error")
                return
            }
            body()
            self.manager.saveToPreferences { (error) in
                guard error == nil else {
                    NSLog("DNSProxySample.App: save error")
                    return
                }
                NSLog("DNSProxySample.App: saved")
            }
        }
    }
}

Questions/Issues:

  1. Why isn't startProxy or handleNewFlow called? Is there anything wrong in the setup?
  2. How do I mention custom DNS address?
1 Answers
Related