Highlight
Apple 网络安全团队的 Qiaoyu Deng 讲解了 DNS 安全的根本问题以及 iOS 16/macOS Ventura 中的两个解决方案:DNSSEC(DNS 安全扩展)和 DDR(DNS 发现机制)。
核心内容
一次 HTTPS 请求看起来很安全。
用户输入域名,App 建立 TLS 连接,服务器证书通过校验,后续数据都被加密。问题在更早的一步:连接开始前,系统必须先用 DNS 把域名解析成 IP 地址。
这一步长期缺少两个能力。
第一,传统 DNS 响应没有认证。攻击者如果让解析器缓存错误地址,客户端可能连到恶意主机。第二,传统 DNS 查询没有加密。网络中的观察者可以看到用户查询过哪些域名。
这场 session 给出两条路径。DNSSEC 用数字签名认证 DNS 响应,解决“地址真实性”问题。DDR(Discovery of Designated Resolvers,指定解析器发现)让设备自动发现同一网络中的加密 DNS 解析器,解决“查询过程会不会被旁路观察”这个问题。
详细内容
DNSSEC 先解决认证
(03:39)iOS 16 和 macOS Ventura 开始支持客户端 DNSSEC 校验。DNSSEC 给 DNS 响应附加数字签名。如果响应被篡改,签名就无法匹配,客户端可以丢弃这个响应。
DNSSEC 还会认证“不存在”。演讲用 NSEC record 举例:如果一个 zone 里按字母顺序只有 A.org、C.org、E.org,NSEC record 可以证明 D.org 不应该存在,也可以证明攻击者不能谎称 A.org 不存在。
更完整的校验依赖信任链。客户端从目标域名的地址、签名和 key 开始,逐级向父 zone 查询,直到 root。设备里预装 root trust anchor。只要 root key 的 hash 能匹配预装 anchor,客户端就能建立从目标 IP 地址到 root 的信任关系。
启用前先检查域名基础设施
(07:45)Apple 明确给了两个前置条件。
第一,域名要支持 IPv6。在 IPv6-only 环境里,IPv4-only 地址会被转换成合成 IPv6 地址。对已经签名的域名来说,合成地址无法通过 DNSSEC 校验。结果是 DNSSEC 打开后,这些地址不可达。
第二,DNS 服务商要给域名做 DNSSEC 签名。如果 App 要求 DNSSEC,但域名没有签名,用户得不到认证收益,只会增加 DNS 流量,并延长解析时间。
所以 DNSSEC 不适合先在客户端盲目打开。它要求 App、域名和 DNS 服务商一起准备好。
在 URLSession 的 session 级别要求 DNSSEC
(09:01)如果一组请求都连接到你控制的、已经签名并支持 IPv6 的域名,可以在 URLSessionConfiguration 上统一开启 DNSSEC。
let configuration = URLSessionConfiguration.default
configuration.requiresDNSSECValidation = true
let session = URLSession(configuration: configuration)
关键点:
- 第 1 行创建默认
URLSessionConfiguration。 - 第 2 行把
requiresDNSSECValidation设为true,要求这个 session 发出的请求完成 DNSSEC 校验。 - 第 3 行用修改后的 configuration 创建
URLSession。
这个设置会影响从该 session 创建的所有 URL request。适合你的 API 域名已经完成 DNSSEC 部署,并且你希望整组请求都使用经过认证的地址。
在单个 URLRequest 上要求 DNSSEC
(09:38)如果只有少数请求需要更严格的 DNS 认证,可以把要求放在 URLRequest 上。
var request = URLRequest(url: URL(string: "https://www.example.org")!)
request.requiresDNSSECValidation = true
let (data, response) = try await URLSession.shared.data(for: request)
关键点:
- 第 1 行创建一个指向目标域名的
URLRequest。 - 第 2 行只为这一个 request 开启 DNSSEC 校验。
- 第 3 行用
URLSession.shared.data(for:)发起请求。
演讲说明,这个 session task 只有在 DNSSEC 校验完成后才会启动。这个粒度适合登录、支付、设备注册等少数关键请求,也适合逐步迁移已有网络层。
在 Network.framework 连接上要求 DNSSEC
(10:08)如果 App 直接使用 Network.framework,可以在 NWParameters 上开启同样的要求。
let parameters = NWParameters.tls
parameters.requiresDNSSECValidation = true
let connection = NWConnection(host: "www.example.org", port: .https, using: parameters)
关键点:
- 第 1 行创建使用 TLS 的
NWParameters。 - 第 2 行要求 DNSSEC 校验。
- 第 3 行用这些参数创建到目标 host 和 HTTPS 端口的
NWConnection。
连接启动后,只有在 DNSSEC 校验完成,并且系统已经连接到经过验证的 IP 地址时,连接才会进入 ready 状态。DNSSEC 打开后,系统只会使用通过校验的地址建连。
DNSSEC 失败时不会返回一个专门错误
(10:46)DNSSEC 的失败模型和 HTTPS 不同。HTTPS 错误会通过 API 报告。DNSSEC 校验失败时,系统不会返回一个“DNSSEC validation failed”错误。
收到未通过校验的响应,等同于没有收到响应。
如果某个 DNS provider 篡改响应,地址不会通过认证检查,会被直接丢弃。设备加入另一个没有篡改响应的网络后,解析会自动恢复。
演讲列了几个失败来源:DNS 响应被修改;设备无法到达预装 trust anchor,因而无法建立信任链;网络不支持 DNSSEC 所需协议,例如 DNS over TCP 或携带 DNSSEC enablement bit 的 EDNS0 option;已签名域名不支持 IPv6,导致合成 IPv6 地址校验失败。
DDR 自动启用加密 DNS
(13:09)DNSSEC 解决认证,但 DNS 查询本身仍可能是明文。iOS 14 和 macOS Big Sur 已经提供加密 DNS:可以用 App 里的 NEDNSSettingsManager,或 profile 中的 DNSSettings,手动配置系统级加密 DNS;也可以用 NWParameters 上的 PrivacyContext 让 App 选择加密 DNS。
(13:47)iOS 16 和 macOS Ventura 新增自动路径。如果当前网络支持 DDR,DNS 查询会自动使用 TLS 或 HTTPS。
设备加入新网络时,会对 _dns.resolver.arpa 发起 Service Binding query。支持 DDR 的 DNS server 会返回一个或多个配置。设备再用这些信息建立到 designated resolver 的加密连接。
设备还会验证一件事:未加密 resolver 的 IP 地址必须包含在 designated resolver 的 TLS certificate 里。这样可以确认未加密解析器和加密解析器属于同一实体。验证通过后,设备默认使用加密 DNS。
DDR 只对当前单个网络生效。只有当前网络支持,设备才会自动使用加密 DNS。演讲还指出,如果 DNS server 的 IP 地址是 private IP address,DDR 不工作,因为这类地址不能放进 TLS certificate,所有权也无法验证。
企业加密 DNS 可以使用客户端认证
(16:32)iOS 16 和 macOS Ventura 还支持在加密 DNS 配置里指定 client authentication。入口是 NEDNSSettingsManager 或 DNSSettings profile。
企业环境里,DNS server 可能需要先验证客户端身份,再允许访问。现在可以通过 NEDNSSettings 的 identityReference 属性配置 client certificate。演讲把它类比为 VPN 的 client certificate,并说明它同时适用于 DNS over TLS 和 DNS over HTTPS。
核心启发
1. 给关键 API 请求加 DNSSEC 开关
- 做什么:先只保护登录、支付、设备绑定这类关键请求。
- 为什么值得做:
URLRequest.requiresDNSSECValidation可以把影响范围限制在单个请求,避免一次性改变整套网络层。 - 怎么开始:确认域名支持 IPv6,并由 DNS 服务商完成 DNSSEC 签名;然后在这些请求的
URLRequest上开启requiresDNSSECValidation。
2. 为自有 API 域名做 DNSSEC 预检
- 做什么:在发布前检查域名是否已签名、是否支持 IPv6。
- 为什么值得做:演讲明确指出,未签名域名会带来额外 DNS 流量和更长解析时间,IPv4-only 域名在 IPv6-only 网络下会因为合成地址无法校验而不可达。
- 怎么开始:把域名签名状态和 IPv6 记录纳入服务上线 checklist,再决定 App 端是否开启 DNSSEC。
3. 在 Network.framework 客户端中绑定 DNSSEC 要求
- 做什么:对自建长连接、实时通信或自定义协议连接要求使用经过认证的地址。
- 为什么值得做:
NWParameters.requiresDNSSECValidation会让NWConnection只有在 DNSSEC 校验和连接建立完成后进入 ready 状态。 - 怎么开始:创建
NWParameters.tls,设置requiresDNSSECValidation = true,再用该参数创建NWConnection。
4. 给企业网络规划 DDR 和客户端证书
- 做什么:让企业网络中的设备自动切到加密 DNS,并让 DNS server 校验客户端身份。
- 为什么值得做:DDR 可以让设备自动发现 DNS over TLS 或 DNS over HTTPS 配置;
identityReference可以为加密 DNS 配置 client certificate。 - 怎么开始:在网络侧支持
_dns.resolver.arpa的 Service Binding query;在配置侧用NEDNSSettingsManager或DNSSettingsprofile 提供加密 DNS 和 client certificate 配置。
关联 Session
- Enable encrypted DNS — iOS 14 和 macOS Big Sur 引入手动配置加密 DNS 的系统级和 App 级入口,是本场 DDR 自动发现能力的前置背景。
- Replace CAPTCHAs with Private Access Tokens — 同样关注隐私保护下的信任建立,适合和 DNSSEC 的“先认证再连接”思路一起看。
- Reduce networking delays for a more responsive app — 讲网络连接延迟和请求响应速度,能帮助评估 DNSSEC 带来的解析成本。
- Discover Managed Device Attestation — 面向企业设备和服务器信任,和本场的企业加密 DNS 客户端认证形成互补。
评论
GitHub Issues · utterances