ios - 如何在 iOS 11 中使用 NEDNSProxyProvider

标签 ios proxy dns ios11 networkextension

在网络方面,DNS 代理是 iOS 11 最大的功能之一。但他们没有提供太多关于它的文档或示例。有一个 talk在上面还有他们刚刚描述了 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. 为什么不调用 startProxyhandleNewFlow?设置有什么问题吗?
  2. 如何提及自定义 DNS 地址?

最佳答案

我设法通过系统在 DNSProxyProvider 上触发了 startProxyhandleFlow。我的配置是这样的:

    应用目标上的
  1. 权利 enter image description here
  2. 权利 DNSProxy 扩展 enter image description here 红线类似于:group.com.xzy.project_name

  3. Info.plist 扩展文件 enter image description here

  4. 应用委托(delegate)

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

不要忘记在此处更改 BUNDLE IDENTIFIER 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. 要调试扩展:您的主应用应从运行菜单中选择。从 Xcode 的 Debug 菜单中选择 Attach to Process by PID or Name... 然后输入你的扩展名,按 Attach 按钮。在您看到 Waiting to attach to EXTENSION_NAME on XYZ's iPhone 之后。在 iOS 设备上运行您的应用目标。

关于ios - 如何在 iOS 11 中使用 NEDNSProxyProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45508605/

相关文章:

html - 使用 Safari 时不需要的自动滚动到输入焦点顶部

iphone - Sprite 上的无限滚动(视差)

ios - 无法正确设置 Sprite 的速度

企业代理后面的 Windows 7 上的 Docker VM 主机无法联系代理或更广泛的互联网

dns - 无法访问 cloudfront 和快速文件,网站未加载

c - 尽管未设置 AI_PASSIVE,Getaddrinfo() 返回通配符地址

Azure DNS : Where is it?

javascript - PhoneGap : Notify on Javascript Update

java - 如果我们通过 aop 作用域代理将原型(prototype) bean 注入(inject)到单例 bean 中,getter 如何工作(单例 Bean)?

ios - 通过 ssl 代理读取 iOS 应用程序请求