How to use NEDNSProxyProvider in iOS 11

笑着哭i 提交于 2020-01-12 13:53:08

问题


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:


I managed to trigger startProxy and handleFlow on DNSProxyProvider by system. My configurations are like this:

  1. Entitlements on app target
  2. Entitlements on DNSProxy Extension Red line is something similar to: group.com.xzy.project_name

  3. Info.plist file on Extension

  4. AppDelegate

    import UIKit
    import NetworkExtension
    
    @UIApplicationMain
    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 = "DNS"
                let proto = NEDNSProxyProviderProtocol()
                proto.providerBundleIdentifier = "EXTENSION_BUNDLE_IDENTIFIER_WHICH_HAS_DNS_PROXY"
                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("DNS Test App: load error")
                    return
                }
                body()
                self.manager.saveToPreferences { (error) in
                    guard error == nil else {
                        NSLog("DNS Test App: save error")
                        return
                    }
                    NSLog("DNS Test App: saved")
                }
            }
        }
    }
    

DO NOT FORGET TO CHANGE BUNDLE IDENTIFIER at here proto.providerBundleIdentifier = "EXTENSION_BUNDLE_IDENTIFIER_WHICH_HAS_DNS_PROXY"

  1. DNSProxyProvider

    import NetworkExtension
    
    class DNSProxyProvider: NEDNSProxyProvider {
    
        override init() {
            NSLog("DNSProxyProvider: init")
            super.init()
        }
    
        override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
            NSLog("DNSProxyProvider: startProxy")
            completionHandler(nil)
        }
    
        override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
            NSLog("DNSProxyProvider: stopProxy")
            completionHandler()
        }
    
        override func sleep(completionHandler: @escaping () -> Void) {
            NSLog("DNSProxyProvider: sleep")
            completionHandler()
        }
    
        override func wake() {
            NSLog("DNSProxyProvider: wake")
        }
    
        override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
            NSLog("DNSProxyProvider: handleFlow")
            if let tcpFlow = flow as? NEAppProxyTCPFlow {
                let remoteHost = (tcpFlow.remoteEndpoint as! NWHostEndpoint).hostname
                let remotePort = (tcpFlow.remoteEndpoint as! NWHostEndpoint).port
                NSLog("DNSProxyProvider TCP HOST : \(remoteHost)")
                NSLog("DNSProxyProvider TCP PORT : \(remotePort)")
            } else if let udpFlow = flow as? NEAppProxyUDPFlow {
                let localHost = (udpFlow.localEndpoint as! NWHostEndpoint).hostname
                let localPort = (udpFlow.localEndpoint as! NWHostEndpoint).port
                NSLog("DNSProxyProvider UDP HOST : \(localHost)")
                NSLog("DNSProxyProvider UDP PORT : \(localPort)")
            }
            return true
        }
    
    }
    
  2. As a last step run the app on a real iOS Device.

  3. If you want to display extension logs open Console.app from your Mac.

  4. To debug the extension: Your main app should be selected from run menu. Select Attach to Process by PID or Name... from Xcode's Debug menu and then type your extension's name, press Attach button. After you see the Waiting to attach to EXTENSION_NAME on XYZ's iPhone. Run your app target on a iOS device.



来源:https://stackoverflow.com/questions/45508605/how-to-use-nednsproxyprovider-in-ios-11

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!