web-dev-qa-db-ja.com

iOS11でNEDNSProxyProviderを使用する方法

ネットワーク側では、DNSプロキシはiOS 11の最大の機能の1つです。しかし、DNSプロキシはそれに関する多くのドキュメントやサンプルを提供していません。 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. startProxyまたはhandleNewFlowが呼び出されないのはなぜですか?セットアップに何か問題がありますか?
  2. カスタムDNSアドレスについてどのように言及しますか?
13
mayuur

システムによってstartProxyhandleFlowDNSProxyProviderをトリガーすることができました。私の構成は次のようになります。

  1. アプリターゲットの資格enter image description here
  2. DNSProxy拡張機能の資格enter image description here 赤い線は次のようなものです:group.com.xzy.project_name

  3. 拡張機能のInfo.plistファイル enter image description here

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

ここでバンドル識別子を変更することを忘れないでください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デバイスでアプリターゲットを実行します。

3
abdullahselek