问题
On the networking side, DNS Proxy is one of the biggest features of iOS 11. But they haven't provided much documentation or samples regarding it. There's a talk on it as well where they have just given a description of what is possible with DNS Proxy.
I want to create a working sample of it but didn't get success till now. So I have created a Network Extension with DNS Proxy entitlements and added a DNS Proxy Provider. Here's the code:
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
}
}
Then in AppDelegate, I declare a NEDNSProxyManager and use it as:
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")
}
}
}
}
Questions/Issues:
- Why isn't
startProxy
orhandleNewFlow
called? Is there anything wrong in the setup? - How do I mention custom DNS address?
回答1:
I managed to trigger startProxy
and handleFlow
on DNSProxyProvider
by system. My configurations are like this:
- Entitlements on app target
Entitlements on DNSProxy Extension Red line is something similar to: group.com.xzy.project_name
Info.plist file on Extension
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") } } } }
DO NOT FORGET TO CHANGE BUNDLE IDENTIFIER at here 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") 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 } }
As a last step run the app on a real iOS Device.
If you want to display extension logs open Console.app from your Mac.
To debug the extension: Your main app should be selected from run menu. Select
Attach to Process by PID or Name...
from Xcode's Debug menu and then type your extension's name, pressAttach
button. After you see theWaiting to attach to EXTENSION_NAME on XYZ's iPhone
. Run your app target on a iOS device.
来源:https://stackoverflow.com/questions/45508605/how-to-use-nednsproxyprovider-in-ios-11