may*_*uur 13 dns proxy ios networkextension ios11
在网络方面,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
}
}
Run Code Online (Sandbox Code Playgroud)
然后在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")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
疑问/问题:
startProxy或handleNewFlow被叫?设置有什么问题吗?我设法通过系统触发startProxy和handleFlow开启DNSProxyProvider。我的配置是这样的:

应用程序委托
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")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)不要忘记在此处更改捆绑标识符proto.providerBundleIdentifier = "EXTENSION_BUNDLE_IDENTIFIER_WHICH_HAS_DNS_PROXY"
DNS代理提供者
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
}
}
Run Code Online (Sandbox Code Playgroud)作为最后一步,在真正的iOS 设备上运行该应用程序。
如果您想显示扩展日志,请从您的 Mac打开Console.app。
调试扩展:您的主应用程序应从运行菜单中选择。选择Attach to Process by PID or Name...从Xcode的调试菜单,然后键入您的扩展名,按Attach按钮。看到后Waiting to attach to EXTENSION_NAME on XYZ's iPhone。在 iOS 设备上运行您的应用目标。