16

在网络方面,DNS 代理是 iOS 11 的最大功能之一。但他们没有提供太多关于它的文档或示例。还有一个关于它的讨论,他们刚刚描述了 DNS 代理的可能性。

我想创建一个工作样本,但直到现在还没有成功。因此,我创建了一个具有 DNS 代理权利的网络扩展,并添加了一个 DNS 代理提供程序。这是代码:

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
    }

}

然后在 AppDelegate 中,我声明一个 NEDNSProxyManager 并将其用作:

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")
            }
        }
    }
}

问题/问题:

  1. 为什么不startProxy或不handleNewFlow叫?设置有什么问题吗?
  2. 如何提及自定义 DNS 地址?
4

1 回答 1

7

我设法通过系统触发startProxyhandleFlow开启DNSProxyProvider。我的配置是这样的:

  1. 应用目标上的 权利在此处输入图像描述
  2. DNSProxy Extension 在此处输入图像描述 红线上的权利类似于:group.com.xzy.project_name

  3. 扩展名上的Info.plist文件 在此处输入图像描述

  4. 应用委托

    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")
                }
            }
        }
    }
    

不要忘记在这里更改捆绑标识符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. 作为最后一步,在真正的iOS 设备上运行应用程序。

  3. 如果要显示扩展日志,请从 Mac打开Console.app 。

  4. 调试扩展:应该从运行菜单中选择您的主应用程序。Attach to Process by PID or Name...从 Xcode 的Debug菜单中选择,然后输入你的扩展名,按下Attach按钮。看到后Waiting to attach to EXTENSION_NAME on XYZ's iPhone。在 iOS 设备上运行您的应用程序目标。

于 2018-03-01T16:05:49.887 回答