1082 字
3 分钟
为什么 DNS 使用 UDP 协议
DNS(Domain Name System)是互联网的「电话簿」,将人类可读的域名转换为 IP 地址。你可能知道 DNS 通常使用 UDP 53 端口,但为什么呢?TCP 不是更可靠吗?
一、DNS 协议基础
1.1 DNS 查询类型
DNS 主要有两种查询方式:
flowchart TB
subgraph 递归查询
C[客户端] --> R[递归 DNS]
R --> A[权威 DNS]
end
subgraph 迭代查询
C2[客户端] --> R2[根 DNS]
R2 --> C2
C2 --> T[TLD DNS]
T --> C2
C2 --> A2[权威 DNS]
end
1.2 DNS 报文结构
DNS 报文分为 Header、Question、Answer、Authority、Additional 五个部分:
┌─────────────────────────────────────────────────────┐│ DNS 报文结构 │├─────────────────────────────────────────────────────┤│ Header (12 字节) ││ ├─ Transaction ID (2) ││ ├─ Flags (2) ││ ├─ Questions (2) ││ ├─ Answer RRs (2) ││ ├─ Authority RRs (2) ││ └─ Additional RRs (2) │├─────────────────────────────────────────────────────┤│ Question Section ││ ├─ QNAME (可变长度) ││ ├─ QTYPE (2) ││ └─ QCLASS (2) │├─────────────────────────────────────────────────────┤│ Answer Section (重复的 RR 格式) │└─────────────────────────────────────────────────────┘二、UDP vs TCP:核心对比
2.1 为什么默认用 UDP?
| 特性 | UDP | TCP |
|---|---|---|
| 连接建立 | 无(0 RTT) | 3 次握手(1.5 RTT) |
| 开销 | 8 字节头部 | 20 字节头部 + 选项 |
| 可靠性 | 无(应用层处理) | 确认、重传、排序 |
| 速度 | 快 | 较慢 |
| 资源消耗 | 低 | 高 |
DNS 查询的特点:
- 查询频繁:每次访问网站都要查询
- 数据量小:通常一个 DNS 响应 < 512 字节
- 低延迟要求:DNS 阻塞会导致整个网页加载慢
- 可容忍少量丢包:丢了重试即可
2.2 DNS 的可靠性设计
虽然 UDP 本身不可靠,但 DNS 在应用层实现了可靠性:
sequenceDiagram
participant C as DNS 客户端
participant S as DNS 服务器
C->>S: 查询(UDP)
alt 超时未收到响应
C->>S: 重试查询
C->>S: 重试查询
C->>S: 切换 TCP
end
Note over C,S: 应用层重试机制弥补 UDP 不可靠性
超时重试是 DNS 客户端的标准行为:
- 首次查询,等待 2-5 秒
- 超时后重试(通常 2-3 次)
- 可以切换到 TCP 重新查询
三、DNS 何时使用 TCP?
3.1 响应超过 512 字节
传统的 DNS 协议设计:
- UDP 响应限制在 512 字节(不含 IP 和 UDP 头部)
- 超过限制的响应会被截断
# 使用 dig 查看 DNS 响应大小dig @8.8.8.8 google.com +short
# 查看详细信息,包括 TCP 切换dig @8.8.8.8 google.com +tcp +noall +answer3.2 EDNS(Extension Mechanisms for DNS)
EDNS0 扩展了 DNS:
# 无 EDNSdig @8.8.8.8 cloudflare.com +short
# 有 EDNS(UDP 缓冲区扩展到 4096 字节)dig @8.8.8.8 cloudflare.com +edns=0 +short3.3 DNSSEC
DNSSEC 签名增加的数据量:
普通 A 记录响应:~200 字节DNSSEC 签名后:~1500 字节(常见)DNSSEC 响应经常超过 UDP 限制,触发 TCP。
3.4 区域传输(Zone Transfer)
DNS 服务器之间同步数据时,使用 TCP:
sequenceDiagram
participant P as 主 DNS
participant S as 从 DNS
S->>P: AXFR 请求 (TCP)
P->>S: 完整区域数据 (多个 TCP 包)
Note over P,S: 数据量大,需要 TCP 可靠性
3.5 TCP 使用场景总结
| 场景 | 说明 |
|---|---|
| 响应 > 512 字节 | EDNS 扩展后通常 > 4096 |
| DNSSEC 验证 | 签名数据量大 |
| 区域传输 | AXFR/IXFR 需要完整数据 |
| 客户端显式请求 | 某些客户端偏好 TCP |
四、性能优化:UDP 的优势
4.1 零连接开销
DNS 查询的高频性使得连接建立开销不可忽视:
每分钟网页浏览 ~60 次 DNS 查询
每次 TCP 连接:- 3 次握手 = 1.5 RTT- 假设 RTT = 50ms- 每次连接耗时 75ms- 60 次 = 4.5 秒
每次 UDP 查询:- 0 RTT- 几乎无连接开销4.2 缓存放大攻击的防御
DNS 的 UDP 特性也带来了安全隐患:
flowchart LR
A[攻击者] -->|小请求| D[DNS 服务器]
D -->|大响应| V[受害者]
Note over A,V: 放大倍数可达 50-100 倍
防御措施:
- RRL(Response Rate Limiting):限制响应速率
- EDNS Client Subnet(ECS):限制放大范围
- Anycast:分散流量
五、DoH 和 DoT:加密时代
5.1 DNS 明文的问题
传统 DNS 有隐私问题:
flowchart LR
U[用户] -->|DNS 查询(明文)| I[ISP/中间人]
I -->|修改响应| U
I -->|监视| U
Note over U: 你的 DNS 查询被监控/篡改
5.2 DoT(DNS over TLS)
端口 853,使用 TLS 加密:
# 测试 DoT$ dig @8.8.8.8 cloudflare.com +tls; TLS connection established to 8.8.8.8:8535.3 DoH(DNS over HTTPS)
通过 HTTPS 传输 DNS:
flowchart LR
U[用户] -->|DNS 查询(加密)| G[DoH 服务器]
G -->|查询| D[DNS 服务器]
Note over U,G: 查询被 HTTPS 隐藏
主流 DoH 提供商:
- Cloudflare:
https://cloudflare-dns.com/dns-query - Google:
https://dns.google/dns-query - AdGuard:
https://dns.adguard.com/dns-query
六、DNS 协议设计智慧
6.1 最少化的交换
DNS 查询只需要:
- 1 个请求(客户端 → 服务器)
- 1 个响应(服务器 → 客户端)
TCP 需要:
- 3 次握手
- 1 个请求
- 1 个响应
- 4 次挥手
6.2 无状态设计
DNS 服务器处理请求后不需要保持任何状态:
TCP:保持连接状态UDP:无连接,每个请求独立无状态意味着:
- 服务器更容易扩展
- 可以使用 Anycast 负载均衡
- 单个请求失败不影响其他
6.3 应用层可靠性
DNS 在应用层实现了类似 TCP 的可靠性:
| DNS 特性 | TCP 对应 |
|---|---|
| 超时重试 | 确认与重传 |
| 事务 ID | 序列号 |
| 随机端口 | 随机初始序列号 |
七、IPv6 与 DNS
7.1 AAAA 记录
IPv6 地址使用 AAAA 记录(4 倍 A 记录长度):
# IPv4 A 记录$ dig A example.com +short93.184.216.34
# IPv6 AAAA 记录$ dig AAAA example.com +short2606:2800:220:1::247a:28b5:60877.2 IPv6 对 DNS 的影响
- AAAA 记录更长,响应更容易超过 512 字节
- 促进 EDNS 和 TCP 的采用
- DoH/DoT 的普及也受益于 IPv6 过渡
八、总结
DNS 选择 UDP 作为主要协议,是性能和实用性的平衡:
| 考量 | 决策 |
|---|---|
| 高频查询 | 避免 TCP 握手开销 |
| 小响应 | UDP 512 字节足够 |
| 可容忍重试 | 应用层可靠性足够 |
| 无状态扩展 | UDP 更适合 |
| 隐私需求 | 推动 DoH/DoT |
理解 DNS 协议的设计,可以看到:协议选择不是追求「最可靠」,而是「最合适」。
参考资料
- RFC 1035: Domain Implementation and Specification — DNS 协议标准
- How DNS Works — DNS 可视化解释
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
为什么 DNS 使用 UDP 协议
https://blog.souloss.com/posts/why-the-design/why-dns-uses-udp/ 部分信息可能已经过时
相关文章 智能推荐
1
为什么 UDP 头只有 8 个字节
技术科普 深入解析 UDP 协议头部设计,为什么只有 8 字节,以及与 TCP 头部的对比。
2
为什么 TCP/IP 协议会拆分数据
技术科普 深入解析 TCP/IP 协议数据分片的原因,MTU、MSS 的概念,以及为什么会出现粘包问题。
3
为什么 TCP 协议有性能问题
技术科普 深入解析 TCP 协议的性能瓶颈——队头阻塞、连接创建开销、拥塞控制等设计考量。
4
为什么 TCP 协议有粘包问题
技术科普 深入解析 TCP 粘包问题的本质,为什么 TCP 是字节流协议,以及如何正确处理消息边界。
5
为什么 TCP 协议有 TIME_WAIT 状态
技术科普 深入解析 TCP TIME_WAIT 状态的成因、作用和优化策略,理解连接关闭的复杂性。






