KNOWLEDGE WHY 13 ROOT NAMESERVERS

为什么全球只有 13 组根域名服务器?

DNS UDP 512 字节硬约束 → 数学上限 13 组 → 1995 年定格 → 1400+ anycast 镜像扛起全球解析。

一段话先讲结论

DNS 协议早期被设计为运行在 IPv4 + UDP 上, 单个 UDP 数据包不分片的最大有效载荷上限是 512 字节。根域名服务器列表必须能塞进一个 UDP 应答包 (防止 fallback 到 TCP 导致延迟和复杂度), 按照 DNS 报文的字节布局倒推, 根服务器数量最多能放 13 组。这个数字不是"刚好够用", 而是 1995 年的"协议物理上限",并因数十亿台终端的兼容性而沿用至今。

一、协议层面的硬约束: 512 字节

1.1 IPv4 MTU 与 UDP 不分片

ARPAnet / 早期 IPv4 网络规定最小 MTU 是 576 字节。任何主机都必须能接收这个尺寸的数据包, 否则连最基础的可达性都没法保证 (RFC 791)。

RFC 791 — Internet Protocol, 1981, § 3.1 Total Length
Total Length is the length of the datagram, measured in octets,
including internet header and data.  This field allows the length of
a datagram to be up to 65,535 octets.  Such long datagrams are
impractical for most hosts and networks.  All hosts must be prepared
to accept datagrams of up to 576 octets (whether they arrive whole
or in fragments).  It is recommended that hosts only send datagrams
larger than 576 octets if they have assurance that the destination
is prepared to accept the larger datagrams.
  • 576 字节总长 - IP 头最大 60 字节 - UDP 头 8 字节 = 508 字节 有效载荷上限
  • DNS 实现里向下取整, 定 512 字节 作为软上限 (RFC 1035 § 4.2.1)
  • UDP 响应若超过 512 字节, 必须截断并设置 TC 标志位, 让客户端回退到 TCP — 而 TCP 三次握手会让首次解析延迟翻几倍

这就意味着, "完整的根服务器列表必须能装进一个 512 字节的 UDP 包", 否则全球每次根查询都要走 TCP, 这在 1980s 的硬件上几乎等于宕机。

1.2 DNS 报文的字节分布

一次完整的 "查 . 的 NS 记录" 响应包结构 (服务器返回所有根 NS + 胶水 A 记录):

+-----------------------+
| Header   (12 字节)    |
+-----------------------+
| Question (5 字节)     |   // root "." 仅 1 字节 + QTYPE+QCLASS 4 字节
+-----------------------+
| Answer   (31 + 15(N-1))|  // N 条 NS 记录, 第 1 条全名 + 后续 DNS 压缩指针
+-----------------------+
| Additional (16N 字节) |   // N 条 A 胶水记录 (每条 16 字节)
+-----------------------+

总长公式:

L(N) = 12 + 5 + 31 + 15(N-1) + 16N = 31N + 33

代入 512 字节限制:

31N + 33 ≤ 512 ⇒ N ≤ 15.45

理论上最多 15 组, 但要给 DNSSEC 签名预留空间、EDNS0 OPT 伪记录、字段填充 buffer, 最终定格为 13 组 — 这是 1995 年 RFC 2010 时代锁定的数字, 沿用至今。

1.3 自己实测一下 — `dig -t ns .` 响应 488 字节

上面是理论。现在我们用 dig 命令真的去问根服务器, 看响应到底多大:

terminal — dig -t ns .
$ dig -t ns .

; <<>> DiG 9.10.6 <<>> -t ns .
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35973
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 15

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.                                IN      NS

;; ANSWER SECTION:
.                       14034   IN      NS      h.root-servers.net.
.                       14034   IN      NS      c.root-servers.net.
.                       14034   IN      NS      g.root-servers.net.
.                       14034   IN      NS      a.root-servers.net.
.                       14034   IN      NS      l.root-servers.net.
.                       14034   IN      NS      d.root-servers.net.
.                       14034   IN      NS      f.root-servers.net.
.                       14034   IN      NS      m.root-servers.net.
.                       14034   IN      NS      k.root-servers.net.
.                       14034   IN      NS      i.root-servers.net.
.                       14034   IN      NS      b.root-servers.net.
.                       14034   IN      NS      e.root-servers.net.
.                       14034   IN      NS      j.root-servers.net.

;; ADDITIONAL SECTION:
c.root-servers.net.     1628    IN      A       192.33.4.12
h.root-servers.net.     1628    IN      A       198.97.190.53
b.root-servers.net.     81469   IN      A       170.247.170.2
b.root-servers.net.     58538   IN      AAAA    2801:1b8:10::b
f.root-servers.net.     1628    IN      A       192.5.5.241
m.root-servers.net.     1628    IN      A       202.12.27.33
i.root-servers.net.     1628    IN      A       192.36.148.17
d.root-servers.net.     1628    IN      A       199.7.91.13
g.root-servers.net.     1628    IN      A       192.112.36.4
a.root-servers.net.     1628    IN      A       198.41.0.4
e.root-servers.net.     1628    IN      A       192.203.230.10
j.root-servers.net.     1628    IN      A       192.58.128.30
k.root-servers.net.     1628    IN      A       193.0.14.129
l.root-servers.net.     1628    IN      A       199.7.83.42

;; Query time: 9 msec
;; SERVER: 10.11.56.22#53(10.11.56.22)
;; WHEN: ...
;; MSG SIZE  rcvd: 488

关键看最后一行 — 响应总大小 488 字节 < 512, 跟前面的计算公式完全吻合。如果再加一组 (14 组), 公式 31×14+33 = 467 加上 1 条 A 记录 16 字节后超过 488 + 17×2 = 522 字节, 部分递归 resolver 在没 EDNS0 时就会触发 TCP fallback。 这就是为什么 1997 年定格到 13 组就再没动过。

二、13 组从哪来? 历史演变

这个数字并不是一上来就定的。DNS 的根服务器数量经历过 4 次扩张, 1997 年加入第 13 台 (M-root, WIDE 日本) 后再没动过:

年份数量关键事件
19844DNS 协议初始设计, 全部位于美国
19917增加学术界 / 美国国防部节点
19959RIPE NCC 加入 (K-root) — 欧洲第一台
199713WIDE Project 加入 (M-root) — 亚洲第一台, 数量定格
200713IPv6 双栈支持, 但 IP "组数" 不变
202313Verisign 把 B-root IP 切到 170.247.170.2 (旧 IP 199.9.14.201 退役)

数字定格在 13 后, A~M 字母名永远不变, 只升级硬件、增加 anycast 镜像。 整个互联网的根 hint 文件 (named.root) 早就被烧进了亿万台递归 resolver / stub 客户端的代码里, 改一个数字等于全球升级。

三、但是, 全球真的只有 13 台机器吗?

不是。这是最常见的误解。"13 组根服务器" 指的是 13 个 IP 地址, 不是 13 台物理服务器。

每个 IP 背后是一个 anycast 集群 — 同一个 IP 地址同时被全球数百个数据中心通过 BGP 宣告, 用户的 DNS 查询会被路由到 RTT 最近的镜像。一台 root server "宕机" 一般指某个城市的镜像维护, 全球解析不受影响。

2024 年 13 组根服务器现状

字母运营机构IPv4IPv6Anycast 镜像数
AVerisign198.41.0.42001:503:ba3e::2:3053
B南加州大学 ISI170.247.170.22801:1b8:10::b6
CCogent192.33.4.122001:500:2::c12
D马里兰大学199.7.91.132001:500:2d::d187
ENASA 艾姆斯研究中心192.203.230.102001:500:a8::e254
FISC192.5.5.2412001:500:2f::f274
G美国国防部 NIC192.112.36.42001:500:12::d0d6
H美国陆军研究实验室198.97.190.532001:500:1::5317
INetnod (瑞典)192.36.148.172001:7fe::5375
JVerisign192.58.128.302001:503:c27::2:30168
KRIPE NCC (欧洲)193.0.14.1292001:7fd::1113
LICANN199.7.83.422001:500:9f::42218
MWIDE (日本)202.12.27.332001:dc3::3512
累计 anycast 镜像 (2024)1395

中国大陆 (北京、上海、深圳、广州、合肥等) 部署了 F / I / J / K / L 等多个根服务器的 anycast 镜像节点, 国内查根 RTT 实测通常 < 20ms。

四、EDNS0 之后, 512 字节早就不是限制了

有人会问: 现在 DNS 包 ≥ 4KB 都很常见, 那为啥不"突破 13"?

  • EDNS0 (RFC 6891, 1999) — UDP 包扩展到 4096 字节, 现代 resolver 全部支持
  • DNSSEC 强制使用 EDNS0, 签名数据本身就远超 512 字节
  • TCP fallback — 现代 TCP 三次握手 + TLS / cookies 已经廉价

但根服务器列表已经是 全网共识, 存量超过 90 亿台终端的 stub resolver hint 文件里都写死了这 13 个。 变更动力 = 零, 风险 = 全球互联网断裂, 所以这个数字大概率永远是 13。

一句话: "13 组" 在物理上早就过时, 在工程上不可推翻。

五、总结要点

  1. 历史原因: 1995 年 DNS UDP 512 字节限制 → 数学上限 15 组 → 留 buffer 取 13 组
  2. 协议惯性: 升级数十亿终端的 hint 文件不现实, 永远不动
  3. 真实容量: 1395+ 个 anycast 镜像节点, 单点故障概率近乎零
  4. 中国可达: F / I / J / K / L 多个根在中国大陆有镜像, 实测 RTT < 20ms

延伸阅读

mimetic
mimetic
mimetic