DNS:互联网最被忽视的关键基础设施
一句话结论(30s)
DNS 是互联网的分布式树状「电话簿」,把人类可读的域名翻译成机器可路由的 IP;因为它是分布式分级数据库 + 多级缓存(浏览器 → hosts → 本地 DNS → 权威服务器),所以 90%+ 的查询在本地网内完成、根服务器只处理极小比例——但这也意味着它一旦被劫持或故障,整个互联网就会「消失」而不是「变慢」。
核心原理(2min)
- 树状结构:根 → TLD(com/org/cn)→ 权威(example.com)→ 主机(www 的 A 记录)。
- 递归查询链路:浏览器缓存 → hosts 文件 → 本地 DNS 逐级问根/TLD/权威,客户端只发一份请求等一份响应。
- TTL:控制各层缓存存活时长——CDN 用短 TTL 快速切换 IP 做故障转移,静态站用长 TTL 减少查询。
- 劫持与防御:运营商/路由器/hosts 劫持 → 用 DNSSEC 签名、DoH、DoT 防御。
- 为什么用 UDP:查询通常 < 512 字节、一次请求一次响应,UDP 无连接模型恰好匹配、省三次握手;超大响应(DNSSEC、区域传输)才走 TCP 53。
底层深入(5-10min)
DNS 是什么
DNS(Domain Name System)是互联网的”电话簿”——把人类可读的域名(如 www.example.com)翻译成机器可路由的 IP 地址(如 93.184.216.34)。它是一个分布式、分级的数据库系统。
域名空间的树状结构
. (根)
┌───────────────┼───────────────┐
com org cn
┌─────┴─────┐ ... ...
example google
│
www (A记录 → 93.184.216.34)
每个节点由一个或多个权威 DNS 服务器管理。.com 的权威服务器只认 example.com 的 NS 记录是谁,不存 www.example.com 的具体 A 记录。
思考:为什么 DNS 要设计成「分布式树状」而不是一张大表?因为一张全球集中大表既不现实也不可靠——数十亿域名、每秒上亿次查询,任何单点都扛不住,还会成为唯一故障点。树状分级让每个层级只负责自己的「下一跳」:根只指路到 TLD,TLD 只指路到权威,权威才管具体的 A 记录;责任分散、可横向扩展,任何一层挂了也只影响自己管辖的范围。
完整查询链路
当浏览器请求 www.example.com:
1. 浏览器 DNS 缓存 → 命中?直接返回
2. hosts 文件 → 有配置?直接返回
3. 向本地 DNS 服务器(由 DHCP 配置,如 8.8.8.8)发起递归查询:
a. 本地 DNS → 根域名服务器: "www.example.com 的 IP?"
根: "不知道,但 .com 的权威 DNS 在 ns1.com (IP: x.x.x.x)"
b. 本地 DNS → ns1.com: "www.example.com 的 IP?"
ns1.com: "不知道,但 example.com 的权威 DNS 在 ns1.example.com (IP: y.y.y.y)"
c. 本地 DNS → ns1.example.com: "www.example.com 的 IP?"
ns1.example.com: "A 记录是 93.184.216.34"
4. 本地 DNS 缓存结果(TTL 秒),返回给浏览器
这就是递归查询——本地 DNS 服务器代表客户端逐级查找,客户端只发出一份请求、等待一份响应。
思考:为什么一次
www.example.com解析要「逐级问」而不是一次直达?因为没有任何一个服务器知道全量答案,只知道「谁负责下一级」的索引。本地 DNS 代表客户端一层层问下去,客户端只发一份请求、等一份响应——把复杂度留给本地 DNS,把简单留给客户端。再叠加多级缓存,90%+ 的查询根本到不了根服务器。
TTL 的意义
每条 DNS 记录有 TTL(Time To Live),告诉各级缓存这条记录可以存活多久。CDN 利用短 TTL(几十秒)实现快速切换 IP 做故障转移;静态网站用长 TTL(几小时甚至几天)减少 DNS 查询次数。
思考:TTL 长好还是短好?没有绝对答案,取决于「变更频率 vs 查询成本」的权衡。CDN 要快速切 IP 做故障转移,短 TTL 让变更尽快生效;静态站 IP 几乎不变,长 TTL 减少查询、降低延迟。所以 TTL 本质是「缓存的保鲜期」——越短越新鲜但查询越频繁,越长越省但越难更新。
DNS 劫持
攻击者篡改 DNS 响应,将域名解析到恶意 IP,用户访问正常域名却被带到钓鱼/恶意站点。
常见劫持手段:
- 运营商劫持:修改 DNS 服务器返回虚假 IP,插入广告或劫持流量
- 路由器劫持:修改路由器的 DNS 配置指向恶意 DNS 服务器
- 本地 hosts 劫持:在用户机器上修改 hosts 文件
防御方案:
- DNSSEC:对 DNS 响应做数字签名,客户端可以验证响应未被篡改
- DoH(DNS over HTTPS):DNS 查询走 HTTPS 加密通道,中间人看不到查询内容也无法篡改
- DoT(DNS over TLS):类似 DoH,但基于 TLS 而不是 HTTP 层
思考:为什么 DNS 这么容易被劫持,根源在哪?因为传统 DNS 是明文 + 无身份验证的——查询和响应都不签名、不加密,任何中间节点都能篡改或伪造。DNSSEC 解决「内容是否被篡改」(数字签名),DoH/DoT 解决「传输是否被偷看和替换」(加密通道),两者一个保真、一个保密,缺一不可。
为什么 DNS 用 UDP?
DNS 的查询通常 < 512 字节(一个域名 + 一个请求类型),响应也很小。UDP 无连接的”一次请求一次响应”模型刚好匹配 DNS 的请求模式,避免了 TCP 三次握手的额外延迟。
超过 512 字节的响应(如 DNSSEC 签名链、区域传输)则用 TCP 53 端口。
思考:为什么 DNS 偏偏用不可靠的 UDP?因为 DNS 的请求模型是「一问一答、数据极小」,UDP 的无连接模型恰好匹配:省掉三次握手和连接维护,一次往返就完成;可靠性由「重试」兜底——丢了就重发一次,比建立 TCP 连接更快。只有当响应超过 512 字节(DNSSEC、区域传输)时,才退回到可靠的 TCP。
总结
DNS 是互联网最被忽视的关键基础设施——它出问题时,不是”慢”,是整个互联网”消失了”。分布式树状结构让它支撑了全球数十亿域名的解析,多级缓存让 90%+ 的查询在本地网内完成,根服务器只处理极小比例的查询。
章末提问
Q1:DNS 解析的完整过程是怎样的?
结论先行:浏览器缓存 → hosts → 本地 DNS 递归查询根 → TLD → 权威服务器逐级查找,最终拿到 A 记录返回。因为没有任何单一服务器知道全量答案,本地 DNS 代表客户端一层层问「谁负责下一级」;多级缓存命中则提前返回,90%+ 的查询在本地完成,根服务器只处理极小比例。
Q2:为什么 DNS 用 UDP 而不是 TCP?
结论先行:因为 DNS 查询通常 < 512 字节、一问一答,UDP 无连接模型恰好匹配、省三次握手、一次往返完成。因为建 TCP 连接的握手和状态维护对「极小的一次性查询」是纯开销,UDP 的不可靠由应用层重试兜底;只有超大响应(DNSSEC、区域传输)才用 TCP 53。
Q3:递归查询和迭代查询的区别是什么?
结论先行:递归查询 = 本地 DNS 替客户端跑完整条链路、返回最终结果;迭代查询 = 每次只返回「下一步该问谁」的指引,客户端自己接着问。因为递归把复杂度集中到本地 DNS、对客户端简单友好(只发一份请求等一份响应),迭代则把逐级查询的负担留给客户端;实际中客户端到本地 DNS 是递归,本地 DNS 向上到根/TLD/权威多为迭代。
Q4:DNS 劫持有哪些手段?怎么防御?
结论先行:常见手段是运营商劫持、路由器劫持、本地 hosts 劫持;防御靠 DNSSEC 签名 + DoH/DoT 加密。因为传统 DNS 明文且无身份验证,中间节点可随意篡改;DNSSEC 用数字签名保证响应未被篡改(保真),DoH/DoT 走加密通道保证内容不被偷看替换(保密),两者一真一密配合防御。
Q5:TTL 在 DNS 里起什么作用?为什么 CDN 用短 TTL?
结论先行:TTL 是各层缓存的「保鲜期」,控制记录被缓存多久;CDN 用短 TTL 是为了快速切换 IP 做故障转移。因为 TTL 是变更频率与查询成本之间的权衡——短 TTL 让新 IP 尽快生效(几十秒内全网更新),代价是查询更频繁;静态站 IP 不变,用长 TTL 减少查询、降低延迟。