DNS是互联网的地址簿,负责把域名转换为IP地址。传统DNS查询通常基于UDP 53端口发起,报文既不加密也不校验完整性,任何能观察到网络流量的人都可以知道用户正在访问哪个网站。更严重的是,DNS响应可以被篡改,用户可能在毫不知情的情况下连接到一个伪造的服务器。DoH(DNS over HTTPS)通过把DNS查询放到HTTPS连接中传输,从根本上改变了这种不安全的状态。

一、DoH的工作原理:二进制DNS报文进入HTTPS通道
DoH并没有重新发明DNS协议,而是替换了DNS报文的传输载体。传统DNS报文由头部、问题区、应答区等部分组成,查询和响应都使用同一套二进制编码。DoH的关键在于,客户端把已经编码好的DNS报文直接放进HTTP请求体中,服务器从请求体里取出这些字节,再执行正常的DNS解析流程。标准DoH使用application/dns-message作为MIME类型,请求方法可以是POST或GET。POST请求直接携带二进制DNS报文,GET请求则把二进制内容做Base64url编码后放在dns参数中。
由于DoH运行在HTTPS的443端口上,它天然继承了TLS加密、服务器身份校验和HTTP语义。与普通网页流量相比,DoH请求在网络上看起来就像一次普通的HTTPS请求,很难从端口或明文特征上区分。更重要的是,HTTP/2和HTTP/3支持连接复用,多个DNS查询可以共用同一条TLS连接,避免了传统DNS每次查询都发起独立UDP数据包的握手负担。服务端通过一个URL模板暴露DoH端点,例如https://dns.google/dns-query,客户端会根据预设或动态发现机制访问这个地址。
# 使用 curl 调用 Google 的 DoH JSON 接口查询 A 记录 curl -s 'https://dns.google/resolve?name=ippipp.com&type=A' \ -H 'accept: application/dns-json'
上面的命令展示的是Google提供的JSON格式DoH接口,它便于调试和理解返回内容。但RFC 8484定义的标准DoH接口使用二进制DNS报文,而不是JSON。下面使用Python的dnspython库向标准DoH端点发送原始DNS查询。
import dns.message
import dns.query
import requests
# 构造标准DNS查询报文
query = dns.message.make_query('ippipp.com', 'A')
wire = query.to_wire()
# 使用POST方式发送二进制DNS报文到DoH端点
response = requests.post(
'https://dns.google/dns-query',
data=wire,
headers={'content-type': 'application/dns-message'},
timeout=5,
)
# 将二进制响应还原为DNS响应对象
answer = dns.message.from_wire(response.content)
for rrset in answer.answer:
print(rrset)
从代码可以看到,应用程序无需理解DoH内部的HTTP细节,仍然处理的是标准DNS报文。这种设计让现有DNS客户端库可以较容易地接入DoH,只需把原本发往UDP或TCP socket的数据改成通过HTTPS发送即可。对于需要兼容现有DNS生态的场景,这种方式减少了改造工作量。
二、DoH与传统DNS及DoT的对比
传统DNS、DoT(DNS over TLS)和DoH三者的核心差异在于传输层。传统DNS使用UDP 53端口,响应报文不具备加密和完整性保护,攻击者可以监听、篡改甚至伪造响应。DoT在TCP 853端口上建立TLS会话,将DNS报文放入TLS记录中传输,虽然解决了明文问题,但使用独立端口,防火墙或网络策略只要阻断853端口即可阻止DoT。DoH则复用HTTPS 443端口,与网页流量完全混合,从网络管理的角度看更难被单独识别和封锁。
| 特性 | 传统DNS | DoT | DoH |
|---|---|---|---|
| 传输端口 | UDP/TCP 53 | TCP 853 | TCP 443 |
| 加密 | 无 | TLS | TLS |
| 流量特征 | 明显 | 独立端口可识别 | 与网页HTTPS混合 |
| 额外开销 | 低 | 中等 | 较高但可复用连接 |
DoH的优势还体现在连接复用和HTTP生态上。浏览器、反向代理、负载均衡器都已经具备成熟的HTTPS处理能力,DoH可以直接利用这些基础设施。相比之下,DoT虽然加密更纯粹,但需要单独维护TLS会话,且无法借助HTTP缓存、压缩和连接管理机制。对于普通用户来说,DoH在公共Wi-Fi、运营商网络等不可信环境下能提供更自然的隐私保护,因为它的流量模式与正常浏览网页几乎没有区别。
不过DoH也带来了一些争议。传统DNS查询分散在各级递归解析器中,而公共DoH服务往往由少数大型提供商运营,解析流量会进一步集中。此外,DoH的握手和HTTP头部开销高于UDP DNS,在弱网或高并发场景下可能增加首包延迟。因此选择DoH还是DoT,往往取决于网络环境、隐私需求以及对集中化风险的接受程度。
三、客户端与服务端部署实践
客户端启用DoH的方式比较多。Firefox和Chrome等浏览器内置了DoH选项,用户可以在隐私与安全设置中开启,并选择默认的Cloudflare或NextDNS等公共解析器。如果想在操作系统层面全局启用,Windows 11允许在设置中手动指定DoH服务器地址;Linux系统则可以通过systemd-resolved或安装dnscrypt-proxy、cloudflared等工具实现本机DNS转发。
服务端部署通常有两种思路。一种是直接使用支持DoH的递归解析器,如Cloudflare的cloudflared、AdGuard Home、PowerDNS dnsdist等。另一种是在现有DNS服务器前面增加一个HTTPS网关,由网关负责解密HTTP请求,再转发给内部递归解析器。对于企业环境,后一种方式更灵活,因为可以在网关层保留审计日志,并将DoH流量纳入统一安全策略。
# 使用 Cloudflare 的 cloudflared 启动本地 DoH 代理 docker run -d --name cloudflared \ -p 5300:53/udp \ -p 5300:53/tcp \ cloudflare/cloudflared:latest \ proxy-dns --upstream https://dns.google/dns-query
上面的命令会在本机5300端口启动一个DNS代理,客户端将DNS请求指向127.0.0.1:5300,cloudflared再把请求通过DoH转发给dns.google。这种方式适合单机或小型局域网环境,无需修改每台终端上的系统DNS设置。对于大型网络,可以在出口路由器或专门的DNS服务器上部署类似的代理,统一处理内网所有DoH请求。
在服务端配置DoH时需要注意证书问题。DoH端点必须使用受信任的HTTPS证书,否则客户端会因证书校验失败而拒绝连接。自建DoH服务通常需要申请Let's Encrypt证书,并把证书配置到反向代理或DoH服务器中。同时,URL路径也需要保持稳定,例如统一使用/dns-query,这样客户端预配置时就不会出现路径不匹配的问题。
四、DoH的安全收益与潜在争议
DoH最直接的收益是隐私保护。DNS查询被加密后,网络中的中间设备无法再通过抓包方式得知用户访问了哪些域名,这可以防止运营商或公共Wi-Fi提供者收集用户的浏览偏好。DoH还借助TLS证书链验证服务器身份,客户端可以确认自己连接到的是真正的Cloudflare或Google解析器,而不是被劫持的假冒服务器。对于经常遭遇DNS污染或投毒的用户来说,DoH能够稳定地绕过基于UDP 53端口的篡改。
然而DoH也带来了新的集中化问题。过去DNS查询通常由本地运营商或用户自行搭建的递归解析器处理,分布相对分散。引入公共DoH后,大量用户的解析请求会集中到少数几家提供商,这些提供商理论上可以拼凑出完整的用户访问行为。如果这些提供商受到法律强制要求或被攻击,用户隐私仍可能泄露。因此一些隐私敏感的用户会自建DoH端点,避免依赖公共解析器。
企业内网中的DoH同样需要谨慎处理。如果员工设备启用了浏览器DoH,DNS查询将绕过企业DNS服务器,安全团队可能无法通过DNS日志发现恶意域名或数据外泄行为。一些企业会通过防火墙检测并阻断已知公共DoH端点,同时部署内部DoH服务,让员工既享受加密解析,又不会绕过安全审计。这种做法需要在安全性和隐私之间找到平衡,而不是简单地禁止或放任。
总体来看,DoH是DNS隐私保护向前迈出的重要一步。它把原本裸露在链路层之上的查询内容隐藏进HTTPS通道,显著提升了中间人攻击的难度。但DoH并不能解决DNS协议本身的所有问题,例如DNSSEC仍然负责验证响应内容的真实性,防止解析结果在递归到权威服务器的路径上被篡改。对于开发者和运维人员来说,理解DoH的传输机制、部署方式以及其带来的集中化和治理挑战,是做出合理技术选型的前提。
DNS over HTTPSDoH隐私保护修改时间:2026-08-25 18:32:28