How to change/add DNS server for connected WiFi in iOS programmatically?

江枫思渺然 提交于 2019-12-19 08:20:24

问题


I want to change/add DNS server for connected WiFi of my iPhone device in iOS programmatically?

The Google Public DNS IP addresses (IPv4) are as follows: 8.8.8.8 8.8.4.4

I want to change/add it as like in attached screenshot programmatically.

Please help. I can manage whether its in Objective-c or Swift. It will be more helpful for me in Objective-c. Thanks in advance.

Dummy/Old DNS server of connected Wi-Fi:-

Required DNS server of connected Wi-Fi:-


回答1:


Look at the Network Extensions classes. With the NETunnelProviderManager class you can set the onDemandRules with a NEEvaluateConnectionRule. The NEEvaluateConnectionRule constructor can take a list of wildcard with top-level-domains (i.e. ["*.com", "*.net", "*.org", "*.io"]) as the domains, and use NEEvaluateConnectionRuleAction.connectIfNeeded as the action. Set the onDemandRules of the NEEvaluateConnectionRule you create with all tlds as the domains. Then create a NEOnDemandRuleEvaluateConnection and set its connectionRules to the NEEvaluateConnectionRule created with all of the top-level-domains, and set its interfaceTypeMatch to NEOnDemandRuleInterfaceType.any. Set the NETunnelProviderManager.onDemandRules with a NEOnDemandRuleEvaluateConnection created this way. If you create a NETunnelProviderManagerand load it and save it as described above, you can then turn it on and off by using the NETunnelProviderManager.isEnabled and NETunnelProviderManager.isOnDemandEnabled properties.

Here is an example class that does exactly that.

import Foundation
import NetworkExtension

public class VPNConnect {
    private static let vpnDescription = "DNS OnDemand to GoogleDNS"
    private static let vpnServerDescription = "OnDemand DNS to GoogleDNS"

    public var manager:NETunnelProviderManager = NETunnelProviderManager()
    public var dnsEndpoint1:String = "8.8.8.8"
    public var dnsEndpoint2:String = "8.8.4.4"

    public var connected:Bool {
        get {
            return self.manager.isOnDemandEnabled
        }
        set {
            if newValue != self.connected {
                update(
                    body: {
                        self.manager.isEnabled = newValue
                        self.manager.isOnDemandEnabled = newValue

                    },
                    complete: {
                        if newValue {
                            do {
                                try (self.manager.connection as? NETunnelProviderSession)?.startVPNTunnel(options: nil)
                            } catch let err as NSError {
                                NSLog("\(err.localizedDescription)")
                            }
                        } else {
                            (self.manager.connection as? NETunnelProviderSession)?.stopVPNTunnel()
                        }
                    }
                )
            }
        }
    }

    public init() {
        refreshManager()
    }

    public func refreshManager() -> Void {
        NETunnelProviderManager.loadAllFromPreferences(completionHandler: { (managers, error) in
            if nil == error {
                if let managers = managers {
                    for manager in managers {
                        if manager.localizedDescription == VPNConnect.vpnDescription {
                            self.manager = manager
                            return
                        }
                    }
                }
            }
            self.setPreferences()
        })
    }

    private func update(body: @escaping ()->Void, complete: @escaping ()->Void) {
        manager.loadFromPreferences { error in
            if (error != nil) {
                NSLog("Load error: \(String(describing: error?.localizedDescription))")
                return
            }            
            body()
            self.manager.saveToPreferences { (error) in
                if nil != error {
                    NSLog("vpn_connect: save error \(error!)")
                } else {
                    complete()
                }
            }
        }
    }

    private func setPreferences() {
        self.manager.localizedDescription = VPNConnect.vpnDescription        
        let proto = NETunnelProviderProtocol()
        proto.providerBundleIdentifier = "com.popmedic.vpntunnel.provider"
        proto.serverAddress = VPNConnect.vpnServerDescription
        self.manager.protocolConfiguration = proto
        // TLDList is a struct I created in its own swift file that has an array of all top level domains
        let evaluationRule = NEEvaluateConnectionRule(matchDomains: TLDList.tlds, 
                                                         andAction: NEEvaluateConnectionRuleAction.connectIfNeeded)
        evaluationRule.useDNSServers = [self.dnsEndpoint1, self.dnsEndpoint2]
        let onDemandRule = NEOnDemandRuleEvaluateConnection()
        onDemandRule.connectionRules = [evaluationRule]
        onDemandRule.interfaceTypeMatch = NEOnDemandRuleInterfaceType.any
        self.manager.onDemandRules = [onDemandRule]
    }
}

Please note that you will have to turn the Network Extensions capabilities on and there will be a dialog presented telling the user that you are turning on a VPN connection, but you will not have the [VPN] icon in the status bar when the connection is turned on because we are not setting a vpn, just using the on demand rules.

Here is the TLDList class I used.

Hate Google as much as I do, maybe use this for the DNS you set... Quad9



来源:https://stackoverflow.com/questions/45025200/how-to-change-add-dns-server-for-connected-wifi-in-ios-programmatically

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!