本文档介绍了阿里云公共DNS 在 iOS 14原生加密DNS方案中的接入和开发方式。
概述
DNS解析是网络资源访问的第一跳,iOS 14 开始系统原生支持两种标准规范的 Encrypted DNS, 分别是 DNS over TLS 与 DNS over HTTPS,可以解决以下两个问题:
一、传统Local DNS的查询与回复均基于非加密UDP,发生我们常见的DNS劫持问题。
二、Local DNS Server本身不可信,或者本地Local DNS 服务不可用问题。
针对DNS解析过程中以上两个问题,阿里云公共DNS已经有了解决方案,即使用阿里云公共DNS SDK,但使用SDK会面临一些技术坑,比如302场景的IP直连处理、以及iOS上的SNI问题等,而iOS 14 上的 Encrypted DNS 功能很好的解决了集成SDK的方案存在的问题,您可以参考Demo示例工程源码了解如何设置阿里云公共DNS为加密DNS默认解析器。
iOS 14原生加密DNS方案如何接入阿里云公共DNS
iOS 14 提供了两种设置加密DNS的方法。
第一种方式是针对单个App的所有连接启用加密DNS。
如果您只想为您的App使用加密DNS,而非整个终端系统全部接入使用加密DNS。您可以适配Network.framework的PrivacyContext,只对您的整个App开启加密DNS,App内发起的每个DNS解析都会使用这个配置。
在App范围内使用加密DNS,使用DoH协议示例代码:
import Network
let aliUrl = URL(string: "https://您在控制台注册应用时分配的AccountID.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]))
}
在App范围内使用加密DNS,使用DoT协议示例代码:
import Network
let alidnsHost = NWEndpoint.hostPort(host: "您在控制台注册应用时分配的AccountID.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]))
第二种方式是针对整个终端内所有应用的连接启用加密DNS。
如果您想为整个系统域使用加密DNS,您可以使用NEDNSSettingsManager API编写一个NetworkExtension App完成系统全局加密DNS设置。
通过NetworkExtension设置系统域全局DNS服务器,使用DoH协议示例代码:
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://您在控制台注册应用时分配的AccountID.alidns.com/dns-query")
NEDNSSettingsManager.shared().dnsSettings = dohSettings
NEDNSSettingsManager.shared().saveToPreferences { saveError in
if let saveError = saveError {
// ...handle error...
return
}
}
}
通过NetworkExtension设置系统域全局DNS服务器,使用DoT协议示例代码:
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 = "您在控制台注册应用时分配的AccountID.alidns.com"
NEDNSSettingsManager.shared().dnsSettings = dotSettings
NEDNSSettingsManager.shared().saveToPreferences { saveError in
if let saveError = saveError {
// ...handle error...
return
}
}
}
一条DNS配置包括阿里公共DNS服务器地址、DoT/DoH协议、一组网络规则。网络规则确保DNS设置兼容不同的网络。
网络规则设置示例代码:
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
]
上述代码设置了三个网络规则,第一个规则表示DNS配置应该在SSID=“MyWorkWiFi”的WiFi网络生效,但对私有企业域名enterprise.example.net不开启;第二个规则表示规则在蜂窝网下应该被禁止使用;第三个NEOnDemandRuleConnect表示DNS配置应该默认开启;因为配置DNS是系统支持的,所以在编写NetworkExtension App时不需要实现Extension程序,只需要在Network Extensions中勾选DNS Settings选项。
运行NetworkExtension App,DNS配置将会被安装到系统,为了让DNS配置生效,需要前往设置->通用->VPN & Network->DNS手动启用。