DNS over HTTPS(DoH)
DoH 把 DNS 报文当作 HTTP 的请求体或查询参数来传。它没有发明新的 DNS 语义,只是借用了 HTTP 已有的一切:连接复用、代理、缓存、认证,以及和普通网页混在一起的流量。
基本形式#
RFC 8484 于 2018 年 10 月发布。一个 DoH 服务由一个 URI 模板描述,最常见的写法是:
https://dns.example/dns-query{?dns}路径 /dns-query 只是惯例,规范没有规定,服务方可以用任意路径。请求与应答的媒体类型都是 application/dns-message,内容就是标准的 DNS 报文,和 UDP 里传的字节完全相同。
RFC 8484 把 HTTP/2 列为建议的最低版本:它的多路复用让多个查询共享一条连接,互不排队。DoH 也可以跑在 HTTP/3 上,规范本身与 HTTP 版本无关。
GET 与 POST#
GET 把报文用 base64url 编码(不带末尾的 = 填充)放进 dns 参数:
GET /dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB HTTP/2
Host: dns.example
Accept: application/dns-messagePOST 把原始报文放在请求体里:
POST /dns-query HTTP/2
Host: dns.example
Content-Type: application/dns-message
Accept: application/dns-message
Content-Length: 33
<33 字节的 DNS 报文>GET 的好处是可以被 HTTP 缓存;POST 的请求更短(不需要 base64 膨胀),也不会把查询内容留在各种访问日志的 URL 字段里。上面例子里的查询是 www.example.com 的 A 记录,正是 RFC 8484 原文的示例。
HTTP 缓存#
DoH 应答可以被浏览器或 HTTP 缓存保存,所以 RFC 8484 规定:应答的 HTTP 新鲜期不应超过其中 DNS 记录的最小 TTL(否定应答则按 SOA 推算的否定缓存时间)。服务器通常用 Cache-Control: max-age=… 表达这一点;缓存把应答交出去时,应当把 DNS 记录的 TTL 减去已经在缓存里停留的时间。
为了让相同的问题产生相同的 URL,RFC 8484 建议客户端把报文 ID 设为 0——在 HTTPS 里,ID 已经不承担配对和防伪的职责。
请求构造器#
输入名字和类型,下面会给出对应的 DNS 报文、base64url 编码和完整的 GET 地址。所有计算都在浏览器本地完成;dns.example 是 RFC 用的示例主机名,使用时换成你的解析器。
生成的十六进制可以粘贴到报文解析工具里逐字段核对。
用命令行试#
curl 自 7.62.0 起支持用 DoH 解析主机名本身:
$ curl --doh-url https://dns.quad9.net/dns-query https://example.com/ -o /dev/null -w '%{http_code}\n'直接发一个 DoH 请求,把二进制应答交给 xxd 看:
$ curl -s -H 'accept: application/dns-message' \
'https://cloudflare-dns.com/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB' | xxdkdig 和 BIND 9.18 之后的 dig 都能直接说 DoH:
$ kdig @1.1.1.1 +https example.com AAAA
$ dig +https @1.1.1.1 example.com AAAAdig 的 +https 默认请求路径是 /dns-query,用 POST;+https-get 改用 GET。
JSON 接口不是标准#
一些公共解析器另外提供 application/dns-json 格式(例如 ?name=example.com&type=AAAA),返回易读的 JSON。这种格式不在 RFC 8484 里,各家的字段和行为略有差别,适合调试和脚本,不适合当作通用的客户端协议。
部署上的取舍#
- 难以单独识别。DoH 和普通 HTTPS 共用 443 端口,只看流量很难区分;对用户是好事,对需要按策略管理解析的网络管理员是麻烦。
- 应用各自为政。浏览器内置的 DoH 会绕过系统解析器,内网域名、hosts 文件、本地过滤可能失效。企业通常用策略关闭浏览器 DoH,或部署自己的 DoH 服务。
- 集中化。默认开启 DoH 的应用往往指向少数几家大型解析器,原本分散在各运营商的查询数据集中到了少数地方。
- 开销。HTTP 头部、HPACK/QPACK 状态、连接管理都比 DoT 重一些。对于保持长连接的客户端,这点开销可以忽略;对于每次只查一两个名字的短连接,就不一定了。
DoH 服务器本身就是一个 HTTPS 站点,CDN、反向代理、HTTP 认证都可以直接套用,这是它比 DoT 更容易部署到现有基础设施上的原因。