WWDC Quick Look 💓 By SwiftGGTeam
Improve DNS security for apps and servers

Improve DNS security for apps and servers

观看原视频

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.orgC.orgE.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。入口是 NEDNSSettingsManagerDNSSettings profile。

企业环境里,DNS server 可能需要先验证客户端身份,再允许访问。现在可以通过 NEDNSSettingsidentityReference 属性配置 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;在配置侧用 NEDNSSettingsManagerDNSSettings profile 提供加密 DNS 和 client certificate 配置。

关联 Session

评论

GitHub Issues · utterances