All Products
Search
Document Center

Native encrypted DNS in iOS 14

Last Updated: Apr 16, 2021

This topic describes how to use Alibaba Cloud Public DNS in iOS 14 that natively supports encrypted Domain Name System (DNS).

Overview

DNS resolution is the first step for network resource access. iOS 14 adds native support for two encrypted DNS protocols: DNS over TLS (DoT) and DNS over HTTPS (DoH). Encrypted DNS resolves the following issues:

1. DNS hijacking. Traditional local DNS queries and responses are transmitted based on non-encrypted User Datagram Protocol (UDP), which is prone to DNS hijacking.

2. Untrusted local DNS servers or unavailable local DNS service.

Public DNS provides SDKs to resolve the preceding issues that occur during DNS resolution. However, the use of Public DNS SDKs involves technical difficulties, such as how to handle the 302 redirect for direct IP address access, how to handle direct IP address access for WebView, and how to solve the Server Name Indication (SNI) issue in iOS. The encrypted DNS feature in iOS 14 can resolve the preceding difficulties. For more information about how to set Public DNS as the default resolver for encrypted DNS queries, see the source code of DoHTestDemo.

Use Public DNS in iOS 14 that natively supports encrypted DNS

You can configure encrypted DNS settings in iOS 14 by using one of the following methods:

1. Set a DNS server as the default system-wide DNS resolver for all apps. If you use a server of Public DNS, you can use NEDNSSettingsManager API to write a NetworkExtension app to configure system-wide encrypted DNS.

The following sample code shows how to use NetworkExtension to set a system-wide DNS server by using the DoH protocol:

import NetworkExtension

NEDNSSettingsManager.shared().loadFromPreferences { loadError in
            if let loadError = loadError {
                // ...handle error...
                return
            }
            let dohSettings = NEDNSOverHTTPSSettings(servers: ["223.5.5.5","223.6.6.6","2400:3200:baba::1","2400:3200::1"])
            dohSettings.serverURL = URL(string: "https://Account ID that is assigned to you when you register your app on the Public DNS page of the Alibaba Cloud DNS console.alidns.com/dns-query")
            NEDNSSettingsManager.shared().dnsSettings = dohSettings
            NEDNSSettingsManager.shared().saveToPreferences { saveError in
                if let saveError = saveError {
                  // ...handle error...
                  return
                }
            }
        }

The following sample code shows how to use NetworkExtension to set a system-wide DNS server by using the DoT protocol:

import NetworkExtension

NEDNSSettingsManager.shared().loadFromPreferences { loadError in
            if let loadError = loadError {
                // ...handle error...
                return
            }
            let dotSettings = NEDNSOverTLSSettings(servers: ["223.5.5.5","223.6.6.6","2400:3200:baba::1","2400:3200::1"])
            dotSettings.serverName = "Account ID that is assigned to you when you register your app on the Public DNS page of the Alibaba Cloud DNS console.alidns.com"
            NEDNSSettingsManager.shared().dnsSettings = dotSettings
            NEDNSSettingsManager.shared().saveToPreferences { saveError in
                if let saveError = saveError {
                  // ...handle error...
                  return
                }
            }
        }

A DNS setting includes a server address of Public DNS, DoT or DoH protocol, and a set of network rules. The network rules ensure that the DNS setting is compatible with different networks.

The following sample code shows how to configure network rules:

let workWiFi = NEOnDemandRuleEvaluateConnection()
     workWiFi.interfaceTypeMatch = .wiFi
     workWiFi.ssidMatch = ["MyWorkWiFi"]
     workWiFi.connectionRules = [NEEvaluateConnectionRule(matchDomains: ["enterprise.example"], andAction: .neverConnect)]
            
     let disableOnCell = NEOnDemandRuleDisconnect()
     disableOnCell.interfaceTypeMatch = .cellular
            
      let enableByDefault = NEOnDemandRuleConnect()
      NEDNSSettingsManager.shared().onDemandRules = [
                workWiFi,
                disableOnCell,
                enableByDefault
      ]

The preceding code configures three network rules. The first rule indicates that the DNS setting takes effect on the Wi-Fi network whose SSID is MyWorkWiFi but does not take effect for enterprise.example.net. The second rule indicates that the DNS setting is disabled on a cellular network. The third rule indicates that the DNS setting is enabled by default. You do not need to implement Extension when you write the NetworkExtension app. You need only to select DNS Settings in Network Extensions to allow iOS 14 to support DNS settings.

setNetworkExtension

Run the NetworkExtension app to add the DNS setting to iOS 14. You must manually enable the DNS setting by going to Settings > General > VPN & Network > DNS.

share

2. Enable encrypted DNS for all or specific connections of a single app.

For example, you can enable encrypted DNS only for your app, but not all apps in the system. You can set the PrivacyContext of Network.framework to enable encrypted DNS for all or specific connections of your app.

The following sample code shows how to enable encrypted DNS for a single connection of an app by using the DoH protocol:

import Network

let privacyContext = NWParameters.PrivacyContext(description: "EncryptedDNS")
        if let url = URL(string: "https://Account ID that is assigned to you when you register your app on the Public DNS page of the Alibaba Cloud DNS console.alidns.com/dns-query") {
            let address1 = NWEndpoint.hostPort(host: "223.5.5.5", port: 443)
            let address2 = NWEndpoint.hostPort(host: "223.6.6.6", port: 443)
            let address3 = NWEndpoint.hostPort(host: "2400:3200::1", port: 443)
            let address4 = NWEndpoint.hostPort(host: "2400:3200:baba::1", port: 443)
            privacyContext.requireEncryptedNameResolution(true, fallbackResolver: .https(url, serverAddresses: [address1,address2,address3,address4]))
        }

The following sample code shows how to enable encrypted DNS for a single connection of an app by using the DoT protocol:

import Network

 let privacyContext = NWParameters.PrivacyContext(description: "EncryptedDNS")
        let alidnsHost = NWEndpoint.hostPort(host: "Account ID that is assigned to you when you register your app on the Public DNS page of the Alibaba Cloud DNS console.alidns.com", port: 853)
        let address1 = NWEndpoint.hostPort(host: "223.5.5.5", port: 853)
        let address2 = NWEndpoint.hostPort(host: "223.6.6.6", port: 853)
        let address3 = NWEndpoint.hostPort(host: "2400:3200::1", port: 853)
        let address4 = NWEndpoint.hostPort(host: "2400:3200:baba::1", port: 853)
        privacyContext.requireEncryptedNameResolution(true, fallbackResolver: .tls(alidnsHost, serverAddresses: [address1,address2,address3,address4]))

If you want to enable encrypted DNS for all connections of an app, you can use the default PrivacyContext. All DNS queries that sent from the app are resolved by using this PrivacyContext.

The following sample code shows how to enable encrypted DNS for all connections of an app by using the DoH protocol:

import Network

if let aliUrl = URL(string: "https://Account ID that is assigned to you when you register your app on the Public DNS page of the Alibaba Cloud DNS console.alidns.com/dns-query"){
            let address1 = NWEndpoint.hostPort(host: "223.5.5.5", port: 443)
            let address2 = NWEndpoint.hostPort(host: "223.6.6.6", port: 443)
            let address3 = NWEndpoint.hostPort(host: "2400:3200::1", port: 443)
            let address4 = NWEndpoint.hostPort(host: "2400:3200:baba::1", port: 443)
            NWParameters.PrivacyContext.default.requireEncryptedNameResolution(true, fallbackResolver: .https(aliUrl, serverAddresses: [address1,address2,address3,address4]))
            }

The following sample code shows how to enable encrypted DNS for all connections of an app by using the DoT protocol:

import Network

let alidnsHost = NWEndpoint.hostPort(host: "Account ID that is assigned to you when you register your app on the Public DNS page of the Alibaba Cloud DNS console.alidns.com", port: 853)
        let address1 = NWEndpoint.hostPort(host: "223.5.5.5", port: 853)
        let address2 = NWEndpoint.hostPort(host: "223.6.6.6", port: 853)
        let address3 = NWEndpoint.hostPort(host: "2400:3200::1", port: 853)
        let address4 = NWEndpoint.hostPort(host: "2400:3200:baba::1", port: 853)
        NWParameters.PrivacyContext.default.requireEncryptedNameResolution(true, fallbackResolver: .tls(alidnsHost, serverAddresses: [address1,address2,address3,address4]))