在网络方面,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") } } } }
疑问/问题:
解决方法
我设法通过系统触发DNSProxyProvider上的startProxy和handleFlow.我的配置是这样的:
>应用目标上的权利
> DNSProxy扩展的权利
红线类似于:group.com.xzy.project_name
> Extension上的Info.plist文件
> AppDelegate
import UIKit import NetworkExtension @UIApplicationMain class AppDelegate: UIResponder,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”
> 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") return false } }
>作为最后一步,在真正的iOS设备上运行应用程序.>如果要显示扩展日志,请从Mac打开Console.app.>要调试扩展名:应从运行菜单中选择主应用程序.从Xcode的Debug菜单中选择Attach to Process by PID或Name …然后输入扩展名,按Attach按钮.在XYZ的iPhone上看到等待附加到EXTENSION_NAME后.在iOS设备上运行您的应用目标.