当客户端电脑访问google.com时,DNS发生哪些行为

客户端访问 https://google.com → 浏览器需要把 google.com 转换成 IP

为例,从浏览器缓存 → OS 缓存 → 本地 DNS → 递归 DNS → Root → .com TLD → Google 权威 DNS → 返回客户端完整走一遍。

先给你一个总览:


                    ┌──────────────────────────────┐
                    │        客户端 Client         │
                    │                              │
访问 google.com ──→ │ ① 浏览器 DNS Cache           │
                    │ ② OS / System DNS Cache      │
                    │ ③ hosts 文件                 │
                    └──────────────┬───────────────┘
                                   │ 没命中
                                   ▼
                         Local DNS / Stub Resolver
                                   │
                                   │ DNS Query
                                   ▼
                    ┌──────────────────────────────┐
                    │ Recursive DNS Server          │
                    │ 递归 DNS / DNS Resolver      │
                    └──────────────┬───────────────┘
                                   │
                    ┌──────────────▼───────────────┐
                    │ Root DNS                      │
                    │ 根 DNS                       │
                    │                              │
                    │ "我不知道 google.com         │
                    │  但 .com 的 DNS 在这里"       │
                    └──────────────┬───────────────┘
                                   │
                                   ▼
                    ┌──────────────────────────────┐
                    │ .com TLD DNS                 │
                    │ 顶级域 DNS                   │
                    │                              │
                    │ "google.com 的权威 DNS       │
                    │  在这里"                     │
                    └──────────────┬───────────────┘
                                   │
                                   ▼
                    ┌──────────────────────────────┐
                    │ Google Authoritative DNS      │
                    │ 权威 DNS                     │
                    │                              │
                    │ google.com → IP              │
                    └──────────────┬───────────────┘
                                   │
                                   ▼
                         Recursive DNS Cache
                                   │
                                   ▼
                              Client
                                   │
                                   ▼
                           Google IP Address
                                   │
                                   ▼
                              TCP/QUIC
                                   │
                                   ▼
                            Google Server

下面把这个过程拆开。

一、首先要明确:到底是谁在问 DNS?

这是很多人第一次学 DNS 时最容易混淆的地方。

假设你在浏览器输入:

https://google.com

浏览器需要知道:


google.com
      ↓
142.250.x.x

但浏览器通常不会自己一路去问 Root、TLD、权威 DNS。

实际上通常是:


Browser
   ↓
OS Resolver / Stub Resolver
   ↓
Local DNS / Configured DNS
   ↓
Recursive Resolver
   ↓
Root / TLD / Authoritative

所以这里有一个非常重要的角色划分:

Client

负责:

“我需要知道 google.com 的 IP。”

Recursive DNS

负责:

“你不用管后面怎么查,我替你把答案找到。”

Root / TLD / Authoritative

负责:

“我只告诉你下一步应该问谁。”

二、第一阶段:浏览器自己的 DNS Cache

用户输入:

google.com

浏览器首先可能检查自己的 DNS 缓存。

例如:

Browser DNS Cache

google.com
↓
142.250.72.14
TTL remaining = 120s

如果还没有过期:

google.com
↓
Browser Cache
↓
142.250.72.14

那么整个 DNS 查询到这里就结束了。

不会访问 OS,也不会访问 Local DNS。

这就是第一层缓存。

三、如果浏览器没有缓存怎么办?

假设:

Browser Cache

google.com
↓
MISS

浏览器就会把域名解析交给操作系统。

例如 Linux:

Application
↓
glibc / resolver
↓
/etc/resolv.conf

Windows 则由 Windows DNS Client 等组件处理。

四、第二阶段:OS/System DNS Cache

操作系统本身通常也会存在 DNS 缓存。

例如:

OS DNS Cache

google.com
↓
142.250.72.14

如果命中:

Browser
↓
OS DNS Cache HIT
↓
142.250.72.14

结束。

如果:

OS Cache MISS

继续。

五、hosts 文件

这里还有一个非常重要的环节:

hosts

Linux:

/etc/hosts

Windows:

C:\Windows\System32\drivers\etc\hosts

例如:

142.250.72.14 google.com

那么系统可能直接得到:

google.com
↓
hosts
↓
142.250.72.14

根本不需要 DNS 查询。

所以严格来说:

Browser Cache
↓
OS Resolver
↓
hosts / local mechanisms
↓
DNS Server

具体先后顺序会因 OS、浏览器和 resolver 实现而不同。

六、终于到了 Local DNS

假设:

Browser Cache MISS
OS Cache MISS
hosts MISS

那么客户端需要真正发送 DNS Query。

通常客户端不会直接问 Root。

它会问一个配置好的 DNS Server。

比如:

192.168.1.1

或者:

8.8.8.8

或者:

1.1.1.1

或者公司内部 DNS:

10.10.10.53

这里要区分一个非常重要的概念:

Local DNS ≠ Root DNS

比如家庭网络:

PC
↓
192.168.1.1
↓
ISP DNS

这里的:

192.168.1.1

可能只是你的路由器。

它可能自己有 DNS Cache,也可能把请求转发给 ISP DNS。

而企业网络可能:

Client
↓
10.10.10.53
↓
Corporate DNS

所以我们可以把:

Local DNS

理解成:

客户端配置的、离客户端比较近的 DNS 服务。

它可能同时也是 Recursive Resolver,也可能只是一个 Forwarder。

七、真正的核心:Recursive DNS Server

假设客户端发:

DNS Query:

QNAME = google.com
QTYPE = A

意思是:

“请告诉我 google.com 的 IPv4 地址。”

例如:

Client
|
| UDP/53
| google.com A?
↓
Recursive DNS

注意:

客户端通常只需要问 Recursive DNS

客户端并不知道:

Root Server 是谁
.com TLD 是谁
google.com Authoritative DNS 是谁

这些工作全部由 Recursive Resolver 完成。

八、Recursive DNS 首先检查自己的 Cache

这是整个 DNS 性能非常关键的地方。

Recursive DNS 收到:

google.com A?

先查自己的缓存。

例如:

Recursive DNS Cache

google.com A
↓
142.250.72.14
TTL = 180s

如果命中:

Client
↓
Recursive DNS
↓
Cache HIT
↓
142.250.72.14

直接返回。

整个过程甚至:

Client → Recursive DNS

一次来回就结束。

九、如果 Recursive DNS 也没有缓存呢?

现在进入 DNS 真正的:

递归 + 迭代

假设 Recursive DNS:

google.com A
↓
CACHE MISS

那么 Recursive Resolver 就开始替客户端寻找答案。

注意这里非常重要:

Client → Recursive DNS 是“递归查询”。

而:

Recursive DNS → Root → TLD → Authoritative 是“迭代查询”。

这是 DNS 最重要的概念之一。

十、什么叫 Recursive Query?

客户端:

Client
|
| google.com A ?
↓
Recursive Resolver

客户端实际上是在说:

“你帮我把最终答案找出来。”

所以 Recursive Resolver 要负责完成整个查询链。

客户端不需要知道后面的事情。

十一、Recursive DNS 去问 Root

Recursive DNS 首先需要知道:

.com 在哪里?

于是它向 Root DNS 发:

google.com A?

注意:

Root 并不会告诉它:

google.com = 142.250.72.14

Root 不负责 google.com 的最终解析。

Root 只负责顶级域。

它会告诉 Recursive DNS:

我不知道 google.com

但是:

.com

的 TLD DNS 在这里。

大致可以理解成:

Recursive Resolver
|
| google.com A?
↓
Root
|
| .com NS = ...
↓
Recursive Resolver
十二、Root DNS 到底是什么?

DNS 根区域:

.

注意最后这个点。

完整域名其实是:

google.com.
↑
root

所以:

google
↓
com
↓
.

域名实际上是一个树。

.
Root Zone
|
+------------+------------+
| | |
com org net
|
google
|
www

Root 负责知道:

.com
.net
.org
.cn
.jp
...

这些 TLD 到底由哪些 DNS 服务器负责。

十三、Root 返回什么?

例如逻辑上:

google.com A?

Root:

Answer:
没有 google.com 的 A

Authority:
.com NS ...

Additional:
.com nameserver IPs

这叫:

Referral

也就是:

“我不知道答案,但我告诉你下一步去哪里问。”

所以 Root 的作用可以理解成:

Root
↓
告诉你 .com 去哪里问
十四、Recursive Resolver 接着问 .com TLD

现在 Recursive Resolver 获得:

.com TLD DNS

于是:

Recursive Resolver
|
| google.com A?
↓
.com TLD

TLD DNS 也不会直接告诉你:

142.250.x.x

因为它通常也不知道 Google 的具体 A 记录。

它只知道:

google.com 这个域是谁负责的?

于是它返回:

google.com NS

例如逻辑上:

google.com
↓
ns1.google.com
ns2.google.com
...

真实环境中的 Google DNS 委派和具体服务器可能随时变化,这里只讨论机制。

十五、于是进入 Authoritative DNS

Recursive Resolver 现在知道:

google.com 的权威 DNS 在这里

于是:

Recursive Resolver
|
| google.com A?
↓
Google Authoritative DNS

这次问题终于问到了真正负责:

google.com

这个 Zone 的 DNS Server。

十六、什么叫 Authoritative DNS?

这是另一个核心概念。

假设 Google 有一个 DNS Zone:

google.com

里面可能存在:

google.com A
www.google.com A
mail.google.com MX
google.com MX
...

权威 DNS 保存这些 DNS 数据。

所以:

Root

负责:

.com 在哪里?
TLD

负责:

google.com 在哪里?
Authoritative DNS

负责:

google.com 到底是什么?
www.google.com 到底是什么?
十七、Authoritative DNS 返回最终答案

Recursive Resolver:

Q:

google.com A?

Authoritative DNS:

A:

google.com
↓
142.250.x.x

于是:

Authoritative
↓
142.250.x.x
↓
Recursive Resolver

这才是最终答案。

十八、Recursive Resolver 为什么还要缓存?

因为刚刚辛辛苦苦查了一遍:

Root
↓
.com
↓
Authoritative
↓
google.com

如果下一个用户又问:

google.com

难道再查一遍?

当然不需要。

Recursive DNS 会缓存:

google.com A
↓
142.250.x.x
TTL = 300

所以:

User A
↓
Recursive DNS
↓
Root
↓
TLD
↓
Authoritative

第一次很慢。

但是:

User B
↓
Recursive DNS
↓
Cache HIT

非常快。

这就是 DNS Cache 的核心价值。

十九、TTL 到底在哪里发挥作用?

假设权威 DNS 返回:

google.com A

142.250.x.x

TTL = 300

意思并不是:

这个 IP 300 秒以后就失效。

而是:

递归 DNS 可以把这个 DNS 答案缓存最多 300 秒。

例如:

00:00
查询权威 DNS
TTL = 300

00:01
Cache TTL = 240

00:02
Cache TTL = 180

...

00:05
TTL = 0

Cache Expired

然后 Recursive Resolver 需要重新查询。

二十、最终返回 Client

Recursive Resolver 得到:

google.com A

142.250.x.x

然后返回给客户端:

Recursive DNS
|
| google.com A = 142.250.x.x
↓
Client

客户端再把这个结果放入自己的缓存体系。

于是:

Client DNS Cache

google.com
↓
142.250.x.x
TTL remaining = ...

浏览器也可能缓存。

二十一、整个 DNS 流程串起来

现在把全部流程连起来:

User enters google.com
|
↓
┌────────────────┐
│ Browser Cache │
└───────┬────────┘
│ MISS
↓
┌────────────────┐
│ OS DNS Cache │
└───────┬────────┘
│ MISS
↓
┌────────────────┐
│ hosts / local │
└───────┬────────┘
│ MISS
↓
┌────────────────┐
│ Local DNS │
│ / Stub / │
│ Forwarder │
└───────┬────────┘
│
↓
┌────────────────┐
│ Recursive DNS │
│ Cache? │
└───────┬────────┘
│ MISS
↓
┌────────────────┐
│ Root DNS │
│ "." │
└───────┬────────┘
│
│ Referral:
│ ".com → TLD"
↓
┌────────────────┐
│ .com TLD DNS │
└───────┬────────┘
│
│ Referral:
│ "google.com
│ → NS"
↓
┌────────────────────┐
│ Google Authoritative│
│ DNS │
└─────────┬──────────┘
│
│ A = IP
↓
Recursive DNS
│
│ Cache
↓
Client
│
↓
Google IP
│
↓
TCP / TLS / QUIC
│
↓
Google Server
二十二、这里最容易混淆的:递归 vs 迭代

我建议你把这个概念单独记下来。

Client → Recursive DNS

属于:

Recursive Query

客户端说:

“帮我找到最终答案。”

Recursive DNS → Root

属于:

Iterative Query

Recursive DNS 问:

“google.com 在哪里?”

Root 回:

“我不知道,但是 .com 在这里。”

Recursive DNS → TLD

继续:

“google.com 在哪里?”

TLD 回:

“我不知道具体 IP,但是 Google 的权威 DNS 在这里。”

Recursive DNS → Authoritative

最后:

“google.com A 是什么?”

Authoritative:

“这是最终答案。”

所以:

Recursive
Client ───────────────────→ Resolver
"给我最终答案"

Iterative

Resolver ──→ Root
"google.com?"
Root ───────→
".com 在那里"

Resolver ──→ .com TLD
"google.com?"
TLD ────────→
"Google Authoritative 在那里"

Resolver ──→ Authoritative
"google.com A?"
Authoritative
─────→
"142.250.x.x"
二十三、为什么客户端不直接问 Root?

这是一个非常好的问题。

理论上客户端当然可以:

Client
↓
Root

但实际上普通客户端通常不会这么做。

原因是:

  1. Root 不提供最终解析服务

Root 主要负责:

delegation

它告诉你:

.com 在哪里

而不是:

google.com = xxx
2. 效率非常差

如果每个客户端都自己:

Client
↓
Root
↓
TLD
↓
Authoritative

整个互联网会产生巨大的 DNS 查询量。

  1. Cache 可以大幅降低查询量

Recursive Resolver:

Millions of Clients
|
↓
Recursive Resolver
|
↓
Cache

大量用户共享一个 DNS Cache。

二十四、真正的 DNS 架构其实是这样的

你可以把互联网 DNS 想象成一个巨大的分层数据库:

Root
.
|
+------------+------------+
| | |
.com .org .cn
|
google.com
|
Authoritative
|
DNS Records

每一层只负责自己的区域。

二十五、一个非常关键的概念:Delegation

Root 不需要知道:

google.com

的所有记录。

它只需要知道:

.com

由谁管理。

所以:

Root
↓
.com NS

然后 .com 又不需要知道:

www.google.com

的 IP。

它只需要知道:

google.com

由谁管理。

于是:

Root
↓
.com
↓
google.com
↓
Authoritative DNS

这就是:

DNS Delegation
二十六、如果访问的是 www.google.com 呢?

流程稍微更有意思。

假设:

www.google.com

那么 DNS 树:

www
|
google
|
com
|
.

查询:

www.google.com A?

Recursive Resolver:

Root
↓
.com TLD
↓
google.com Authoritative
↓
www.google.com
↓
A / CNAME

这里可能出现:

www.google.com
↓
CNAME
↓
某个 canonical name
↓
A
↓
IP

所以 DNS 查询不一定一次就得到 A。

可能还需要继续解析 CNAME。

二十七、AAAA 又是什么?

如果客户端支持 IPv6,它可能同时查询:

google.com A
google.com AAAA

其中:

A
↓
IPv4

而:

AAAA
↓
IPv6

例如:

google.com
|
+── A ────→ IPv4
|
└── AAAA ─→ IPv6

实际客户端如何查询、是否并行查询,以及最终选哪个地址,会受到操作系统、浏览器和网络栈策略影响。

二十八、DNS 查询的网络层面

传统 DNS:

Client
|
| UDP 53
↓
DNS Server

一般使用:

UDP/53

但在一些情况下会使用:

TCP/53

例如 DNS 响应较大、需要可靠传输或特定协议场景。

现代加密 DNS 还包括:

DoT
DNS over TLS
TCP 853

以及:

DoH
DNS over HTTPS
TCP 443

所以你看到:

google.com

真正发生的网络行为可能是:

Application
↓
OS Resolver
↓
DoH / DoT / UDP DNS
↓
Recursive Resolver
二十九、还有一个非常容易搞错的地方:Local DNS 和 Recursive DNS

比如:

PC
↓
192.168.1.1
↓
8.8.8.8

那么:

192.168.1.1

可能是:

Local DNS Forwarder

而:

8.8.8.8

才是真正的:

Recursive Resolver

于是:

Client
↓
Local DNS / Router
↓
Recursive DNS
↓
Root
↓
TLD
↓
Authoritative

但也有可能:

Client
↓
Local DNS
↓
Root/TLD/Auth

因为 Local DNS 本身就是 Recursive Resolver。

所以:

Local DNS 是“位置/角色上的称呼”,Recursive DNS 是“功能上的称呼”。

这是理解 DNS 架构非常重要的一点。

三十、最终形成一个完整的“角色地图”
组件 做什么
Browser Cache 浏览器缓存 DNS 结果
OS Cache 操作系统缓存 DNS 结果
hosts 本机静态域名映射
Local DNS 客户端附近的 DNS 服务/转发器
Recursive Resolver 代客户端完成完整 DNS 查询
Root DNS 告诉你 TLD 在哪里
TLD DNS 告诉你某个域的 Authoritative 在哪里
Authoritative DNS 保存并回答该 Zone 的权威记录
DNS Cache 根据 TTL 缓存结果
Client 最终获得 IP 并连接目标服务器
三十一、最重要的一张图

如果你要真正把 DNS 学懂,我建议脑子里始终保持下面这张图:

DNS Hierarchy
│
▼
Root "."
│
"Who handles .com?"
│
▼
.com TLD DNS
│
"Who handles google.com?"
│
▼
Google Authoritative DNS
│
"google.com A = X"
│
▼
Recursive Resolver
│
Cache
│
▼
Local DNS
│
▼
Client
│
▼
IP Address
│
▼
TCP/QUIC + TLS
│
▼
Google

而整个过程中最核心的逻辑其实就两句话:

客户端对 Recursive DNS 发起递归请求:帮我找到 google.com。

Recursive DNS 对 DNS 层级结构进行迭代查询:Root → TLD → Authoritative,最终拿到答案并缓存,再返回客户端。


下一步继续深入,我们专题直接进入 “DNS 报文级别”:
拿一次 google.com A 查询,把 Client → Local DNS → Recursive → Root → TLD → Authoritative 每一跳的 源 IP、目的 IP、UDP 53、Transaction ID、Flags、Question、Answer、Authority、Additional、Referral、Glue、TTL 全部拆开。这样就从“理解 DNS”进入到“能抓包分析 DNS”。

我们进入 DNS 抓包级别。这一层非常关键:前面讲的是“DNS 在做什么”,现在我们开始看每一个 DNS Packet 到底长什么样、每一跳在问什么、为什么返回 Referral、Glue、TTL,以及 Recursive Resolver 是怎么一步一步走完整棵 DNS 树的。

  1. 先建立一个抓包视角

假设客户端:

Client IP = 192.168.1.100

本地 DNS:

Local DNS = 192.168.1.1

Recursive DNS:

Recursive Resolver = 8.8.8.8

目标:

google.com

我们假设缓存全部 MISS。

整个过程可以抽象成:

Client
192.168.1.100
|
| ① DNS Query
| google.com A?
↓
Local DNS
192.168.1.1
|
| ② Forward
↓
Recursive Resolver
8.8.8.8
|
| ③ google.com A?
↓
Root
|
| ④ Referral → .com
↓
.com TLD
|
| ⑤ Referral → google.com NS
↓
Google Authoritative DNS
|
| ⑥ Answer → IP
↓
Recursive Resolver
|
| ⑦ Answer + Cache
↓
Local DNS
|
| ⑧ Answer
↓
Client

注意:

①~② 和 ⑦~⑧ 是“客户端侧的 DNS 请求/响应”。

而:

③~⑥ 是 Recursive Resolver 自己在 DNS 层级中进行的迭代查询。

  1. 第一包:Client → Local DNS

客户端发:

google.com A?

通常类似:

Source IP = 192.168.1.100
Destination IP = 192.168.1.1

Source Port = 53124
Destination = 53

Protocol = UDP

DNS Payload:

Transaction ID = 0x3a7c
Flags = 0x0100

Question:
QNAME = google.com
QTYPE = A
QCLASS = IN

这里已经出现了几个非常重要的字段。

  1. DNS Header

DNS Header 通常是 12 bytes:

+---------------------+
| Transaction ID |
+---------------------+
| Flags |
+---------------------+
| QDCOUNT |
+---------------------+
| ANCOUNT |
+---------------------+
| NSCOUNT |
+---------------------+
| ARCOUNT |
+---------------------+

也就是:

Transaction ID
Flags
Question Count
Answer Count
Authority Count
Additional Count
4. Transaction ID 是干什么的?

假设:

Transaction ID = 0x3a7c

Client 发:

0x3a7c
google.com A?

DNS Server 返回:

0x3a7c
google.com A = ...

客户端通过 Transaction ID 知道:

这个 Response 是对应我刚才发出的哪个 Query。

类似于:

Request ID = 12345

Response ID = 12345

所以抓包的时候经常可以看到:

Query:
ID = 0x3a7c

Response:
ID = 0x3a7c
5. Flags 是 DNS 最值得学习的字段之一

例如 Query:

Flags = 0x0100

其中:

QR = 0

表示:

Query

如果:

QR = 1

表示:

Response
RD:Recursion Desired

Client 发给 Recursive DNS 时通常:

RD = 1

意思:

我希望你帮我递归解析。

也就是:

Client
|
| RD=1
↓
Recursive Resolver

"Please recurse for me."
6. Response 里面最重要的 Flags

假设 Recursive DNS 返回:

Flags:

QR = 1
AA = 0
RA = 1

分别是:

QR = 1

这是 Response。

RA = 1

表示:

Recursive service available

也就是:

“我可以帮你做递归查询。”

而:

AA = 0

表示:

这个服务器不是 google.com 这个 Zone 的权威服务器。

这个非常重要。

  1. AA:Authoritative Answer

假设你直接问 Google Authoritative DNS:

google.com A?

它回答:

AA = 1

表示:

这个答案来自我所负责的权威 Zone。

所以:

Recursive Resolver
AA = 0

Authoritative DNS
AA = 1

这就是抓包时判断“谁是真正权威回答者”的重要线索。

  1. Question Section

刚才的 Query:

Question:

QNAME:
google.com

QTYPE:
A

QCLASS:
IN

这里:

QNAME
google.com
QTYPE
A

表示:

IPv4 地址。

QCLASS
IN

Internet。

  1. Recursive Resolver 收到 Query

现在:

Client
↓
192.168.1.1
↓
Recursive DNS

假设 Recursive Resolver 的 cache 是:

google.com A
↓
MISS

它开始自己查。

  1. 第二阶段:Recursive → Root

这里非常重要。

Recursive DNS 不再把:

RD = 1

带给 Root。

它是在进行迭代查询。

逻辑上:

Recursive Resolver
|
| google.com A?
↓
Root

Query 里面通常:

RD = 0

意思:

“Root,你不用帮我递归,你告诉我下一步去哪里。”

  1. Root 为什么能回答?

Root 不知道:

google.com = IP

但是它知道:

.com

由谁负责。

所以 Root 返回:

Answer:
可能为空

Authority:
.com NS ...

这就是:

Referral
12. Referral 是 DNS 的核心机制

假设 Root 返回:

Authority Section:

com. NS a.gtld-servers.net.
com. NS b.gtld-servers.net.
com. NS c.gtld-servers.net.
...

意思:

.com 这个 Zone 的权威 DNS 是这些服务器。

所以:

Root
↓
".com 你去问这些服务器"

而不是:

Root
↓
"google.com = 142.250.x.x"
13. 为什么还需要 Additional Section?

这里进入一个非常关键的概念:

Glue Record

假设 Root 告诉你:

.com NS = a.gtld-servers.net

那么 Recursive Resolver 下一步要连接:

a.gtld-servers.net

但问题来了:

a.gtld-servers.net 自己的 IP 是多少?

如果必须再次解析:

a.gtld-servers.net

就可能陷入:

我要找 .com
↓
问 Root
↓
Root 告诉我 a.gtld-servers.net
↓
可是我要先解析 a.gtld-servers.net
↓
又要问 .net
...

所以 DNS 在 Referral 里面通常会提供必要的:

Additional Section

例如:

a.gtld-servers.net A x.x.x.x
a.gtld-servers.net AAAA yyyy::...

这些用于帮助 Recursive Resolver 找到下一跳 DNS Server。

这就是:

Glue
14. 所以一次 Root Response 可能长这样

逻辑结构:

DNS Response
│
├── Answer
│ └── empty
│
├── Authority
│ ├── com. NS a.gtld-servers.net
│ ├── com. NS b.gtld-servers.net
│ └── ...
│
└── Additional
├── a.gtld-servers.net A x.x.x.x
├── b.gtld-servers.net A x.x.x.x
└── ...

抓包的时候看到:

Answer: 0
Authority: N
Additional: N

并不意味着 DNS 出错。

这可能正是一个正常的 Referral。

  1. Recursive 接着问 .com

现在 Recursive Resolver 已经知道:

.com TLD DNS

于是:

Recursive
|
| google.com A?
↓
.com TLD

同样:

RD = 0

因为这是迭代查询。

  1. .com TLD 会告诉它什么?

.com TLD 不负责:

google.com A

它负责的是:

google.com

这个域的 Delegation。

所以它返回:

Authority:

google.com NS ns1...
google.com NS ns2...
...

逻辑:

.com TLD
↓
"google.com 的权威 DNS 在这里"
17. 又会出现 Glue

如果:

google.com NS = ns1.google.com

那么:

ns1.google.com

本身又属于:

google.com

这就出现了典型的“胶水”需求。

TLD 可以提供必要的:

Additional

帮助 Recursive Resolver 找到:

ns1.google.com

的 IP。

这就是为什么抓包里:

Authority
Additional

经常一起出现。

  1. 现在终于找到 Authoritative DNS

Recursive Resolver:

知道了:

google.com
↓
Authoritative DNS

于是:

Recursive
|
| google.com A?
↓
Authoritative DNS
19. 这一次和前面不一样

现在服务器真正拥有:

google.com

这个 Zone 的权威数据。

所以返回:

Answer:

google.com. A 142.250.x.x

并且:

AA = 1

也就是:

Authoritative Answer。

  1. TTL 出现了

例如:

google.com. 300 IN A 142.250.x.x

这里:

300

就是:

TTL = 300 seconds

意思:

Recursive Resolver 可以把这个答案缓存 300 秒。

  1. Recursive Resolver 收到答案以后干什么?

它不会马上忘掉。

它会建立:

Cache:

google.com
|
+--- A
|
+--- 142.250.x.x
|
+--- TTL = 300

于是未来:

User A
User B
User C
User D
User E
...

全部可能共享这个缓存。

  1. 然后 Recursive DNS 返回客户端

最终:

Authoritative
↓
Recursive
↓
Local DNS
↓
Client

Response:

Transaction ID = 0x3a7c

Flags:
QR = 1
AA = 0
RA = 1

Answer:

google.com.
300
IN
A
142.250.x.x

客户端收到。

  1. 客户端最终拿到什么?

最终客户端只关心:

google.com
↓
142.250.x.x

至于后面发生了:

Root
↓
TLD
↓
Authoritative

客户端甚至可能完全不知道。

这是 Recursive Resolver 帮它完成的。

  1. DNS 完成以后,才开始真正访问 Google

这是另一个非常重要的认知:

DNS 不是访问 Google 本身。

DNS 只是:

Name Resolution

完成:

google.com
↓
IP

然后才进入:

IP
↓
TCP / QUIC
↓
TLS
↓
HTTP

例如 HTTPS:

Browser
|
| DNS
↓
142.250.x.x
|
| TCP 443
↓
TLS
|
| HTTPS
↓
Google

HTTP/3 则可能:

DNS
↓
IP
↓
QUIC / UDP 443
↓
TLS 1.3
↓
HTTP/3
25. 现在我们把抓包过程完整串起来

假设 Wireshark 中看到的是:

① Client → Local DNS

192.168.1.100:53124
↓
192.168.1.1:53

Standard query
google.com A
RD=1
② Local DNS → Recursive

192.168.1.1
↓
8.8.8.8

google.com A
RD=1
③ Recursive → Root

8.8.8.8
↓
Root DNS

google.com A
RD=0

Root:

Answer = 0

Authority:
.com NS ...

Additional:
glue
④ Recursive → .com TLD

8.8.8.8
↓
.com TLD

google.com A
RD=0

TLD:

Answer = 0

Authority:
google.com NS ...

Additional:
glue
⑤ Recursive → Authoritative

8.8.8.8
↓
Google Authoritative DNS

google.com A
RD=0

Authoritative:

Answer:

google.com A 142.250.x.x
TTL 300

AA=1
⑥ Recursive → Local DNS

google.com
↓
142.250.x.x
⑦ Local DNS → Client

google.com
↓
142.250.x.x
⑧ Client → Google

142.250.x.x:443

DNS 阶段结束。

  1. 一个特别重要的细节:并不是每次都会看到 Root → TLD → Auth

现实中绝大多数 DNS 查询并不会完整走这一遍。

因为 Cache。

比如第一次:

Client
↓
Recursive
↓
Root
↓
TLD
↓
Auth

但是第二个用户:

Client
↓
Recursive
↓
CACHE HIT

直接:

google.com
↓
142.250.x.x
27. 更进一步:甚至 Referral 也会缓存

Recursive Resolver 不仅缓存:

google.com A

它还可能缓存 DNS 层级中的 Delegation 信息。

例如:

.com NS
google.com NS

因此即使:

google.com A

缓存失效了,Recursive Resolver 也可能已经知道:

google.com
↓
Authoritative NS

这样就不需要重新从 Root 开始。

所以现实世界里的 DNS Resolver 并不是每次:

Root → TLD → Auth

完整走一遍。

  1. 这就是为什么 DNS 解析通常很快

第一次:

Client
↓
Local DNS
↓
Recursive
↓
Root
↓
TLD
↓
Authoritative

可能几十到几百毫秒。

但之后:

Client
↓
Recursive Cache

可能只需要几毫秒甚至更低。

  1. 最后给你一个“抓包分析口诀”

以后你打开 Wireshark 看到 DNS,不要被一堆字段吓到。

按照这几个问题依次看:

第一问:谁在问谁?
Source IP
Destination IP
第二问:Query 还是 Response?

看:

QR
第三问:要不要递归?

看:

RD
第四问:是不是权威回答?

看:

AA
第五问:这个 Response 到底给了什么?

依次看:

Answer
Authority
Additional
第六问:如果 Answer 是空的,是不是 Referral?

看:

Authority

有没有:

NS
第七问:下一跳 DNS 的 IP 从哪里来?

看:

Additional

有没有:

A
AAAA

也就是 Glue。

第八问:答案能缓存多久?

看:

TTL
30. 你现在应该建立的完整脑图

                    ┌──────────────┐
                    │   Browser    │
                    │ DNS Cache    │
                    └──────┬───────┘
                           │ MISS
                           ▼
                    ┌──────────────┐
                    │ OS Resolver  │
                    │ Cache        │
                    └──────┬───────┘
                           │ MISS
                           ▼
                    ┌──────────────┐
                    │ hosts        │
                    └──────┬───────┘
                           │ MISS
                           ▼
                    ┌──────────────┐
                    │ Local DNS    │
                    └──────┬───────┘
                           │
                           ▼
                 ┌───────────────────┐
                 │ Recursive Resolver │
                 │                   │
                 │ Cache             │
                 └────────┬──────────┘
                          │ MISS
                          ▼
                     ┌─────────┐
                     │  Root   │
                     │    .    │
                     └────┬────┘
                          │
                     Referral
                          │
                          ▼
                     ┌─────────┐
                     │  .com   │
                     │   TLD   │
                     └────┬────┘
                          │
                     Referral
                          │
                          ▼
                 ┌─────────────────┐
                 │ Authoritative   │
                 │ google.com      │
                 └────────┬────────┘
                          │
                       Answer
                          │
                     A / AAAA
                          │
                          ▼
                 ┌─────────────────┐
                 │ Recursive Cache │
                 └────────┬────────┘
                          │
                          ▼
                       Client
                          │
                          ▼
                    Google IP
                          │
                          ▼
                    TCP/QUIC 443
                          │
                          ▼
                       HTTPS

下一层我建议直接做一个“真实 Wireshark DNS 报文解剖”。 我们可以拿一个典型的 google.com A 查询,逐字段看 Ethernet → IP → UDP → DNS Header → Question → Answer → Authority → Additional,然后再专门讲 Referral / Glue / CNAME / TTL / DNSSEC(尤其是 RRSIG、DNSKEY、DS)。这一层搞明白以后,你基本就具备看真实 DNS 故障抓包的能力了。

我们这一节直接进入 “Wireshark 逐包解剖 DNS”。

下面我会故意把一次完整的 google.com A 查询做成一份虚拟但符合真实 DNS 报文结构的抓包,然后像看 Wireshark 一样逐层拆:

Ethernet → IP → UDP → DNS Header → Question → Answer → Authority → Additional

同时把 Referral、Glue、TTL、CNAME、EDNS、DNSSEC 串起来。

Wireshark 本身也把 dns.id、dns.flags.*、dns.qry.name、dns.resp.ttl、A/AAAA/NS/RRSIG/DNSKEY/DS 等字段作为 DNS 协议字段进行解析。

  1. 先看一张“真实抓包思维图”

我们假设:

Client
192.168.1.100

↓

Local DNS
192.168.1.1

↓

Recursive Resolver
8.8.8.8

↓

Root

↓

.com TLD

↓

google.com Authoritative

但在 Wireshark 中,你可能只在客户端机器上看到:

Client
|
| DNS Query
↓
192.168.1.1
|
| DNS Response
↓
Client

你通常看不到 Recursive → Root → TLD → Authoritative。

因为那些 DNS Packet 是在 Recursive Resolver 和它上游之间传输的。

这点特别重要。

  1. 第一层:Ethernet

假设客户端发 DNS:

Ethernet II

Destination MAC:
aa:bb:cc:dd:ee:ff

Source MAC:
11:22:33:44:55:66

Type:
IPv4

然后进入 IP 层。

所以 Wireshark 左边你会看到:

Frame
└── Ethernet II
└── Internet Protocol Version 4
└── User Datagram Protocol
└── Domain Name System

这就是典型的:

Ethernet
↓
IP
↓
UDP
↓
DNS
3. 第二层:IP

例如:

Internet Protocol Version 4

Source:
192.168.1.100

Destination:
192.168.1.1

Protocol:
UDP

TTL:
64

这里的:

TTL = 64

不是 DNS TTL。

这是 IP Header 里的 TTL。

千万不要混。

  1. 两种 TTL

这是 DNS 初学者最容易混淆的地方。

IP TTL

位于:

IP Header

用于防止 IP Packet 在网络中无限循环。

例如:

IP TTL = 64
DNS TTL

位于:

DNS Resource Record

例如:

google.com
300
IN
A
142.250.x.x

这里:

300

才是 DNS Cache TTL。

所以:

IP TTL ≠ DNS TTL
5. 第三层:UDP

典型 DNS:

User Datagram Protocol

Source Port:
53124

Destination Port:
53

所以:

192.168.1.100:53124
↓
192.168.1.1:53

客户端使用一个临时端口:

53124

DNS Server:

53
6. DNS Header

进入:

Domain Name System (query)

假设:

Transaction ID: 0x3a7c
Flags: 0x0100
Questions: 1
Answer RRs: 0
Authority RRs: 0
Additional RRs: 1

DNS Header 总共 12 bytes。

可以画成:

+--------------------+
| Transaction ID |
+--------------------+
| Flags |
+--------------------+
| QDCOUNT |
+--------------------+
| ANCOUNT |
+--------------------+
| NSCOUNT |
+--------------------+
| ARCOUNT |
+--------------------+

Wireshark 可以直接显示 DNS ID、Query Type、Question/Answer/Authority/Additional 数量等字段。

  1. Transaction ID

例如:

Transaction ID: 0x3a7c

Client:

Query ID = 0x3a7c

Server:

Response ID = 0x3a7c

这样客户端可以匹配:

Query
↓
0x3a7c

Response
↓
0x3a7c
8. Flags 开始真正有意思了

例如 Query:

Flags: 0x0100

拆开:

QR = 0
Opcode = QUERY
AA = 0
TC = 0
RD = 1
RA = 0

其中最值得关注:

QR
RD
RA
AA
TC
RCODE
9. QR
QR = 0

表示:

Query

如果:

QR = 1

就是:

Response

所以 Wireshark 里面:

Standard query

和:

Standard query response

就是这个区别。

  1. RD:Recursion Desired

Client → Recursive DNS:

RD = 1

意思:

我希望你帮我完成递归查询。

也就是:

Client
|
| google.com A?
| RD=1
↓
Recursive Resolver

客户端实际上是在说:

“别只告诉我下一步去哪里,我要最终答案。”

  1. RA:Recursion Available

Response 中:

RA = 1

意思:

这个 DNS Server 提供递归服务。

所以:

RD = 1

是:

Client 请求递归。

而:

RA = 1

是:

Server 表示自己支持递归。

两个完全不同。

  1. AA:Authoritative Answer

如果:

AA = 1

表示:

这个 Response 是来自负责该 Zone 的权威服务器。

例如:

google.com Authoritative

回答:

google.com A 142.250.x.x

那么:

AA = 1

而 Recursive Resolver 返回给客户端:

AA = 0

通常意味着:

我不是 google.com 的权威服务器,我只是把答案找到了。

  1. Question Section

继续往下:

Questions: 1

Name:
google.com

Type:
A

Class:
IN

所以:

google.com A IN

翻译成人话:

我要查询 Internet Class 下 google.com 的 IPv4 地址。

  1. A 到底是什么?

DNS Type:

A = 1

表示:

IPv4 address

Wireshark 的 DNS 类型定义中也明确将 A 标为 host address,同时 NS、CNAME、SOA、MX、TXT 等都是不同的 Resource Record 类型。

例如:

google.com A
↓
142.250.x.x
15. AAAA

如果:

QTYPE = AAAA

表示:

IPv6

例如:

google.com AAAA
↓
IPv6 address

所以:

A
↓
IPv4

AAAA
↓
IPv6
16. 现在看 Response

假设:

Transaction ID:
0x3a7c

Flags:
0x8180

Questions:
1

Answer:
1

Authority:
0

Additional:
1

我们拆 Flags:

QR = 1
RD = 1
RA = 1
AA = 0

翻译:

这是 Response;客户端要求递归;服务器支持递归;但这个服务器不是权威服务器。

这就是典型的:

Client ← Recursive Resolver
17. Answer Section

现在终于出现:

Answer:

google.com
TTL 300
IN
A
142.250.x.x

这就是最终答案。

  1. TTL

例如:

google.com
300
IN
A
142.250.x.x

结构:

Name
TTL
Class
Type
RDATA

其中:

300

是:

TTL = 300 seconds

Wireshark 将 Resource Record 的 TTL 暴露为 dns.resp.ttl。

  1. TTL 不是“IP 存活时间”

这是必须纠正的一个常见误解。

错误理解:

TTL 300 → IP 300 秒后失效。

正确理解:

TTL 300 → 这个 DNS Record 可以被缓存 300 秒。

比如:

google.com
TTL=300
A=142.250.x.x

表示:

DNS Cache
↓
最多缓存 300 秒

不是说:

Google Server
↓
300 秒以后关闭
20. 接下来进入最重要的:Referral

如果 Recursive Resolver 自己没有答案,它去问 Root:

google.com A?

Root 不会给:

google.com A 142.250.x.x

而可能返回:

Answer:
0

Authority:
13 records

Additional:
...

例如:

Authority:

com. NS a.gtld-servers.net.
com. NS b.gtld-servers.net.
com. NS c.gtld-servers.net.
...

这就是:

Referral
21. 为什么 Answer = 0?

因为 Root:

没有 google.com 的 A Record。

但它告诉你:

.com Zone 的 DNS Server 在哪里。

所以:

Answer = 0
Authority > 0

不等于失败。

这是一个非常重要的抓包判断技巧。

  1. 怎么判断这是 Referral?

看:

Answer

为空。

然后:

Authority

里面有:

NS

例如:

com. NS a.gtld-servers.net.

那么你基本可以判断:

这是 delegation / referral。
23. Additional Section

然后你可能看到:

Additional:

a.gtld-servers.net
A
192.5.x.x

或者:

AAAA
2001:...

这就是给 Recursive Resolver 提供下一跳 DNS Server 的地址。

  1. Glue 是什么?

把刚才的逻辑再讲透一点。

Root 告诉你:

.com
NS
a.gtld-servers.net

但是你需要访问:

a.gtld-servers.net

你必须知道它的 IP。

所以 Referral 可能附带:

a.gtld-servers.net
A
x.x.x.x

这就是 Glue/Additional 信息发挥作用的地方。

它让 Resolver 可以:

Root
↓
知道 .com NS
↓
直接知道 NS IP
↓
访问 .com TLD

而不是再次陷入名字解析。

  1. Recursive → TLD

接下来:

8.8.8.8
↓
.com TLD

Query:

google.com A
RD=0

注意:

RD = 0

这意味着:

Recursive Resolver 不要求 .com TLD 替它继续递归。

它自己负责继续下一跳。

  1. TLD Response

TLD:

Answer:
0

但是:

Authority:

google.com
NS
xxx.google...

意思:

我不知道 google.com A,但是我知道 google.com 的权威 DNS。

这又是一个 Referral。

所以你会看到:

Root
↓
Referral to .com

TLD
↓
Referral to google.com NS

Authoritative
↓
Actual Answer
27. Authoritative Response

最终:

google.com
TTL 300
IN
A
142.250.x.x

这次:

AA = 1

因为:

Authoritative DNS

真正负责这个 Zone。

  1. 如果你看到 CNAME 呢?

现实里经常不是:

www.google.com
↓
A
↓
IP

而可能是:

www.example.com
↓
CNAME
↓
something.example.net
↓
A
↓
IP

例如:

www.example.com
CNAME
edge.example.net

那么 Resolver 还要继续解析:

edge.example.net

然后:

edge.example.net
A
1.2.3.4

最终:

www.example.com
↓
CNAME
↓
edge.example.net
↓
A
↓
1.2.3.4
29. 所以 Answer 里可能同时有 CNAME + A

例如:

Answer:

www.example.com
CNAME
edge.example.net

edge.example.net
A
1.2.3.4

这时你不要误以为:

一个 Query 怎么出现两个答案?

因为:

CNAME 本身就是答案的一部分,而目标名字还需要继续解析。

  1. NXDOMAIN 又是什么?

现在假设:

abcxyz123.google.com

根本不存在。

Authoritative DNS 可能返回:

RCODE = NXDOMAIN

意思:

这个域名不存在。

注意:

NXDOMAIN

和:

NOERROR + Answer=0

不是一回事。

  1. 两者区别非常重要
    NXDOMAIN
    这个名字不存在。
    NOERROR + Answer=0
    名字可能存在,但是你问的这个 Record Type 没有。

例如:

google.com

存在。

但是你问:

google.com AAAA

如果没有 AAAA:

RCODE = NOERROR
Answer = 0

这和:

xyz123.google.com

不存在:

RCODE = NXDOMAIN

完全不同。

  1. DNS Negative Caching

这里又会出现一个很重要的 Cache。

假设:

abc.example.com

不存在。

Authoritative:

NXDOMAIN

Resolver 可以缓存这个“不存在”的结果一段时间。

所以:

第一次:
Client
↓
Recursive
↓
Authoritative
↓
NXDOMAIN

第二次:

Client
↓
Recursive
↓
Negative Cache
↓
NXDOMAIN

甚至不需要再访问权威 DNS。

  1. EDNS:你抓包时很可能看到 OPT

现代 DNS Packet 经常不是简单:

Question
Answer
Authority
Additional

你还会看到:

OPT

例如:

Additional Records:
. OPT

这是:

EDNS(0)

它允许 DNS 扩展协议能力,例如更大的 UDP Payload,以及 DNSSEC 相关的 DO bit 等。

Wireshark 也提供 dns.resp.edns0_version、UDP payload size、DO bit 等字段。

  1. DO Bit

如果进行 DNSSEC 查询,你经常看到:

DO = 1

意思:

DNSSEC OK

也就是:

我希望 DNS 响应里包含 DNSSEC 相关数据。

例如:

RRSIG
DNSKEY
DS
NSEC
NSEC3

等。

  1. DNSSEC 开始进入另一套逻辑

普通 DNS:

google.com
↓
A
↓
IP

DNSSEC:

google.com
↓
A
↓
RRSIG
↓
DNSKEY
↓
DS
↓
建立信任链

Wireshark 对 DNSKEY、DS、RRSIG 等都有专门的 DNS 字段解析。

  1. DNSSEC 的核心不是“加密”

这一点非常重要。

DNSSEC:

不是:

DNSSEC
↓
加密 DNS

而是:

DNSSEC
↓
数字签名
↓
验证 DNS 数据真实性

也就是说:

DNSSEC 主要解决 Authenticity / Integrity。

而:

DoH
DoT

主要解决:

DNS 查询传输过程中的隐私和加密。

两者完全是不同维度。

  1. 最终把 Wireshark 里最重要的字段整理一下
    Wireshark 字段 含义
    dns.id Transaction ID
    dns.flags.response Query / Response
    dns.flags.recdesired RD
    dns.flags.recavail RA
    dns.flags.authoritative AA
    dns.flags.truncated TC
    dns.flags.rcode Response Code
    dns.qry.name 查询名称
    dns.qry.type 查询类型
    dns.qry.class 查询 Class
    dns.resp.ttl Resource Record TTL
    dns.a IPv4 A
    dns.aaaa IPv6 AAAA
    dns.resp.ns NS
    dns.rrsig.* DNSSEC RRSIG
    dns.dnskey.* DNSSEC DNSKEY
    dns.ds.* DNSSEC DS

这些字段可以直接对应 Wireshark 的 DNS display-filter 字段体系。

  1. 最后给你一张“DNS 抓包判断表”

以后看到一个 DNS Response,按这个顺序判断:

DNS Response
│
▼
RCODE 是什么?
│
┌───────────┼────────────┐
│ │ │
NOERROR NXDOMAIN 其他
│
▼
Answer 有吗?
│
┌───┴────┐
│ │
有 没有
│ │
▼ ▼
最终答案 看 Authority
│
▼
NS?
│
▼
Referral

然后:

Answer
↓
看 Type
↓
A / AAAA / CNAME / MX / TXT ...

再:

TTL
↓
判断 Cache 生命周期

再:

AA
↓
是不是权威回答?

再:

RA / RD
↓
有没有递归?

最后:

Additional
↓
OPT?
Glue?
EDNS?
DNSSEC?
39. 到这里,你已经可以“读”DNS 包了

真正分析一个 DNS 故障时,你脑子里应该形成这样一条链:

① Client 有没有发 Query?
↓
② Query 到没到 Local DNS?
↓
③ Local DNS 有没有回?
↓
④ RCODE 是什么?
↓
⑤ Answer 有没有?
↓
⑥ 如果没有,Authority 是什么?
↓
⑦ 是不是 Referral?
↓
⑧ 下一跳 NS 的 IP 有没有 Glue?
↓
⑨ Recursive 能不能访问下一跳?
↓
⑩ Authoritative 有没有返回?
↓
⑪ AA 是否正确?
↓
⑫ TTL 多久?
↓
⑬ 是否 CNAME?
↓
⑭ 是否 DNSSEC?
↓
⑮ 最终 Client 是否拿到 IP?

这其实已经是真实 DNS troubleshooting 的基本框架。

下一节建议进入一个非常实战的场景

我们下一步可以直接做:

dig +trace google.com 全流程解剖。

因为 dig +trace 特别适合把刚才讲的理论变成实际:

$ dig +trace google.com

.
↓
.com
↓
google.com
↓
A / AAAA

然后我们
逐行解释:

;; Received ...
;; QUESTION SECTION:
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:


再进一步把 dig google.com、dig +trace google.com、dig @8.8.8.8 google.com、dig @权威DNS google.com 四个命令放在一起比较。

这样你就会彻底理解:

“普通 dig 为什么只看到一个答案,而 +trace 为什么能把 Root → TLD → Authoritative 全部暴露出来。”

.

也就是:

Root Zone
十二、你可能看到类似这样的输出

不同时间、网络和 BIND 版本输出会不同,所以这里重点看结构:

. 518400 IN NS a.root-servers.net.
. 518400 IN NS b.root-servers.net.
. 518400 IN NS c.root-servers.net.
...

这不是:

google.com

的答案。

这是:

Root 告诉你 Root Zone 的 Name Servers。

十三、然后发生什么?

dig +trace 会找到 Root Server。

然后问:

google.com A?

Root:

我不知道 google.com 的 A。

但是:

.com

由这些 TLD DNS Server 管理。

于是出现:

com. IN NS ...
十四、这就是我们前面说的 Referral

你现在终于可以把理论和命令对应起来:

Root
↓
Answer:
0

Authority:
com. NS ...

Additional:
NS IP

也就是:

Answer = 没有最终答案
Authority = 告诉你下一步去哪
Additional = 帮你找到下一跳 Server
十五、接下来 .com

现在 dig +trace 找到了:

.com TLD

于是继续:

.com
↓
google.com?

TLD:

我不知道 google.com 的 A。

但是:

google.com

的权威 DNS 在这里。

于是:

google.com. NS ...

再次 Referral。

十六、然后终于到 Authoritative

现在:

dig +trace

找到了:

google.com Authoritative DNS

于是:

google.com A?

Authoritative:

google.com.
300
IN
A
142.250.x.x

并且这一次:

AA = 1
十七、于是整个 +trace 可以画成
dig +trace google.com
|
↓
Root "."
|
"Where is .com?"
|
↓
.com TLD
|
"Where is google.com?"
|
↓
google.com NS
|
↓
Authoritative DNS
|
"google.com A = X"
|
↓
Final IP

这就是:

DNS Delegation Chain
十八、现在比较两个命令
普通 dig
dig google.com

看到的是:

Client
↓
Recursive DNS
↓
Final Answer
+trace
dig +trace google.com

看到的是:

Root
↓
.com
↓
google.com Authoritative
↓
Final Answer

所以:

dig
= recursive result

dig +trace
= iterative delegation path
十九、第三个非常重要的命令

现在我们直接问 Root。

例如:

dig @a.root-servers.net google.com

这时候你不是让 Root 帮你递归。

你是在直接问 Root:

google.com A?

通常:

RD = 0

Root:

Answer = 0
Authority = .com NS
二十、为什么 Root 不给 IP?

因为:

Root

负责:

.

它知道:

.com
.net
.org
.cn
...

的 delegation。

但是它不负责:

google.com A

所以:

Root
↓
".com 在这里"

而不是:

Root
↓
"Google IP 是 xxx"
二十一、第四个命令:直接问 TLD

假设你从 Root 得到了一个 .com TLD Server:

a.gtld-servers.net

那么可以:

dig @a.gtld-servers.net google.com

你得到:

Answer:
0

Authority:
google.com NS ...

这就是第二次 Referral。

二十二、然后直接问 Authoritative

假设 TLD 告诉你:

google.com NS ...

找到一个权威 DNS 后:

dig @ google.com A

这一次:

Answer:

google.com.
TTL
IN
A
142.250.x.x

并且:

AA

应该是:

1

这才是真正的:

Authoritative Answer
二十三、所以我们可以手工完成 +trace

这非常重要。

+trace 其实可以理解成:

Step 1
找 Root

↓

Step 2
问 Root

google.com?

↓

Step 3
Root 告诉我 .com

↓

Step 4
问 .com

google.com?

↓

Step 5
.com 告诉我 google.com NS

↓

Step 6
问 Authoritative

google.com A?

↓

Step 7
得到 IP
二十四、这就是“递归”和“迭代”的真正区别

现在你应该能彻底理解:

dig google.com

你:

Client
|
| RD=1
↓
Recursive Resolver

"你帮我搞定。"
dig +trace google.com

你实际上:

Client
|
↓
Root

"告诉我下一步。"

↓

.com

"告诉我下一步。"

↓

Authoritative

"给我最终答案。"

所以:

Recursive:
"帮我完成整个任务"

Iterative:
"告诉我下一步该问谁"
二十五、再看 dig +short

普通:

dig google.com

输出很多。

如果你只想:

IP

可以:

dig +short google.com

例如:

142.250.x.x

官方文档也给出了 dig +short example.com 作为只显示简化结果的用法。

二十六、只看 Answer

非常实用:

dig +noall +answer google.com

得到:

google.com. 300 IN A 142.250.x.x

这对于脚本和故障排查非常好。

二十七、查询 NS

比如:

dig google.com NS

你会得到:

google.com.
NS
...

这回答:

google.com 的权威 DNS 是谁?

二十八、查询 MX
dig google.com MX

这回答:

google.com 的邮件服务器是什么?

例如:

google.com.
MX
...

注意:

DNS 不只是:

Name → IP

还有:

Name → Name Server
Name → Mail Server
Name → Alias
Name → Text
...
二十九、查询 CNAME
dig www.example.com CNAME

如果存在:

www.example.com.
CNAME
xxx.example.net.

那么你就知道:

www.example.com
↓
CNAME
↓
xxx.example.net

然后再查:

dig xxx.example.net A
三十、DNS 故障排查开始变得非常有意思

假设用户说:

“浏览器打不开 example.com。”

你不要直接猜。

第一步:

dig example.com

如果:

NOERROR
ANSWER
A

DNS 基本工作。

那么继续查:

TCP
TLS
HTTP

如果:

SERVFAIL

那么可能:

Recursive failure
DNSSEC validation failure
Upstream failure
Delegation problem
Timeout

DNSSEC 验证失败时,递归解析器可能向客户端表现为 SERVFAIL。BIND 官方 DNSSEC 文档也给出了这种典型表现。

如果:

NXDOMAIN

那么:

这个名字不存在。

如果:

NOERROR
ANSWER=0

则需要继续检查:

CNAME
AAAA
A
NS
SOA

以及具体查询的 Record Type。

三十一、一个非常实用的 DNS 排障套路

以后你遇到:

“DNS 有问题。”

直接按这个顺序:

dig google.com

↓

dig @8.8.8.8 google.com

↓

dig +trace google.com

↓

dig google.com NS

↓

dig google.com A

↓

dig google.com AAAA

如果怀疑 CNAME:

dig www.example.com CNAME

如果怀疑 DNSSEC:

dig +dnssec example.com

或者进一步使用:

delv example.com

delv 是 BIND 提供的 DNSSEC-aware 工具;官方文档还说明 delv +ns 可以模拟一个完整递归解析器的迭代过程。

三十二、dig +trace 有一个很重要的细节

很多人以为:

dig +trace google.com

就是:

向你的 Recursive DNS 请求:
"请给我 trace"

不是。

+trace 改变了 dig 的工作方式。

它自己进行:

Root
↓
TLD
↓
Authoritative

的迭代查询。BIND 官方文档明确描述了这一行为。

所以你可以把它理解成:

普通 dig:

┌──────────────┐
│ Recursive DNS│
└──────┬───────┘
↑
│
Client

而:

dig +trace:

Client/dig
│
├────→ Root
│
├────→ TLD
│
└────→ Authoritative
三十三、一个更准确的对比
命令 谁负责递归 主要目的
dig google.com 配置的 DNS Server 普通解析
dig @8.8.8.8 google.com 8.8.8.8 指定 Resolver
dig @root google.com 你自己 观察 Root Referral
dig @TLD google.com 你自己 观察 TLD Referral
dig @Auth google.com 你自己 获取权威答案
dig +trace google.com dig 自己逐级查询 查看完整 delegation chain
三十四、还有一个非常值得你记住的事实

dig +trace 不是严格等价于一个生产 Recursive Resolver 的完整行为。

BIND 文档特别指出,dig +trace 是做 delegation tracing;如果希望更接近 named 本身作为一个 cold-cache recursive resolver 的行为,可以使用 delv +ns。

所以:

dig +trace

特别适合:

教学 / 查看 delegation / DNS troubleshooting

而:

delv +ns

更适合:

模拟递归解析器的解析和验证过程

这个区别以后做高级 DNS 实验时会很有价值。

三十五、现在把整个专题连起来

我们最开始讲:

Browser
↓
OS Cache
↓
Local DNS
↓
Recursive
↓
Root
↓
TLD
↓
Authoritative

现在你已经可以把它映射到工具:

普通访问
─────────────────────────

Browser
↓
OS
↓
Local DNS
↓
Recursive
↓
最终 IP

对应:

dig google.com

而:

Recursive
↓
Root
↓
TLD
↓
Authoritative

对应:

dig +trace google.com

而单独观察每一层:

dig @root-server google.com
dig @tld-server google.com
dig @authoritative-server google.com

这样你就可以手工把 DNS 整棵树拆开检查。

三十六、最后送你一张“DNS 实战地图”

以后看到任何 DNS 问题,先在脑子里跑:


                     DNS Troubleshooting
                              │
                              ▼
                    dig domain.example
                              │
                ┌─────────────┴──────────────┐
                │                            │
             NOERROR                      ERROR
                │                            │
                ▼                            ▼
          Answer 有没有?              RCODE 是什么?
                │                     │
        ┌───────┴──────┐              ├── NXDOMAIN
        │              │              ├── SERVFAIL
       有             无               ├── REFUSED
        │              │              └── TIMEOUT
        ▼              ▼
      A/AAAA        CNAME?
        │              │
        ▼              ▼
       IP           Follow CNAME
                       │
                       ▼
                  dig +trace
                       │
              ┌────────┴────────┐
              ▼                 ▼
            Root               TLD
              │                 │
              ▼                 ▼
           Referral          Referral
              │                 │
              └────────┬────────┘
                       ▼
                 Authoritative
                       │
                       ▼
                 Final Answer
                       │
                       ▼
                      TTL
                       │
                       ▼
                     Cache

下一步我建议我们进入 DNS 专题里非常关键的一关:DNSSEC。

我们可以从真实的:

dig +dnssec google.com

开始,逐个拆:

DNSKEY
↓
DS
↓
RRSIG
↓
NSEC / NSEC3
↓
Root KSK
↓
.com DS
↓
google.com DNSKEY
↓
A + RRSIG

然后解释 “Recursive Resolver 到底怎么判断 DNS 答案是真的,而不是被攻击者伪造的?”——这会把我们前面讲的 Root → TLD → Authoritative 再往上提升一个层次。

好,我们现在进入 DNS 最关键的一层:DNSSEC。

前面我们解决的是:

DNS 怎么找到 google.com?

DNSSEC 要解决的是:

“我找到的 google.com IP,怎么证明它是真的,而不是被人篡改/伪造的?”

DNSSEC 的核心就是 Chain of Trust(信任链):从 Root 的 Trust Anchor 开始,一层一层验证 .com、google.com,最后验证具体的 DNS Record。

  1. 先看整个 DNSSEC 信任链

可以把它想成:

ROOT "."
│
Root Trust Anchor
Root KSK
│
DS(.com)
│
.com
│
DS(google.com)
│
google.com
│
DNSKEY + RRSIG
│
A record
│
142.250.x.x

普通 DNS 的 resolution chain 是:

Root
↓
.com
↓
google.com
↓
A record

DNSSEC 多了一条密码学验证链:

Root Trust Anchor
↓
验证 Root DNSKEY
↓
验证 .com DS
↓
验证 .com DNSKEY
↓
验证 google.com DS
↓
验证 google.com DNSKEY
↓
验证 google.com A

所以:

DNS resolution 是“找到答案”。

DNSSEC validation 是“证明答案可信”。

ICANN 也把 Root Trust Anchor 描述为 DNSSEC 信任链最顶端的可信起点。

  1. DNSSEC 到底增加了哪些 Record?

最重要的 4 个:

Record 作用
DNSKEY 公钥
RRSIG DNS Record 的数字签名
DS 父 zone 对子 zone 公钥的“指纹/承诺”
NSEC/NSEC3 证明某个名字/Record 不存在

可以先记成:

DNSKEY = Key
RRSIG = Signature
DS = Parent → Child 的信任链接
NSEC = Proof of Non-Existence

BIND 官方 DNSSEC 文档也明确把 DNSKEY、RRSIG、NSEC/NSEC3 和父 zone 中的 DS 作为建立 DNSSEC chain of trust 的核心记录。

  1. DNSKEY:公钥在哪里?

假设:

google.com

开启 DNSSEC。

它的 zone 会发布:

google.com. DNSKEY ...

这里面包含 public key。

为什么需要 public key?

因为 authoritative server 生成:

A google.com → 142.250.x.x

以后,还会生成:

RRSIG(A record)

也就是:

A record
+
private key
↓
RRSIG

Resolver 拿到:

A record
RRSIG
DNSKEY

然后使用:

public key

验证:

RRSIG 是否真的对应这个 A record?
4. RRSIG 是什么?

假设:

google.com. 300 IN A 142.250.72.14

普通 DNS:

Question:
google.com A

Answer:
google.com A 142.250.72.14

DNSSEC:

Answer:
google.com A 142.250.72.14

RRSIG:
A record 的数字签名

概念上:

private key
│
▼
A record ──────────► Signature
│
▼
RRSIG

Resolver:

A record
+
RRSIG
+
DNSKEY(public key)
│
▼
cryptographic verification
│
├── PASS → answer authentic
│
└── FAIL → bogus

所以攻击者即使把:

google.com → 142.250.72.14

改成:

google.com → 6.6.6.6

也不能简单地重新生成一个合法的 RRSIG,因为他没有 zone 的 private signing key。

  1. 但这里马上出现一个问题

Resolver 拿到:

google.com DNSKEY

然后用这个 DNSKEY 验证:

google.com A

很好。

但是:

为什么相信这个 DNSKEY 本身是真的?

这是 DNSSEC 最漂亮的地方。

答案:

父 zone 来证明。

也就是:

.com
↓
证明 google.com 的 DNSKEY

具体就是:

google.com DNSKEY
│
▼
hash
│
▼
DS
│
▼
.com zone
6. DS:父 zone 如何“认可”子 zone?

假设:

google.com

有 DNSKEY:

google.com DNSKEY = PublicKeyGoogle

对它做 hash:

hash(PublicKeyGoogle)

得到:

DS

于是 .com zone 保存:

google.com. DS ...

这就形成:

.com
│
│ DS
▼
google.com DNSKEY

所以 DS 可以理解为:

Parent zone 对 Child zone DNSKEY 的密码学承诺。

  1. 再往上一层

但是:

为什么相信 .com 的 DNSKEY?

同样的问题。

答案:

Root
↓
DS(.com)
↓
.com DNSKEY

于是整个链条:

ROOT
│
│ DS(.com)
▼
.com DNSKEY
│
│ DS(google.com)
▼
google.com DNSKEY
│
│ RRSIG
▼
google.com A

这就是:

Chain of Trust

ICANN 对这个机制的描述也是:父 zone 为子 zone 的 key material 提供可验证的信任连接,从 Root 的 trust anchor 开始建立连续的信任链。

  1. Root 为什么可以被信任?

这是 DNSSEC 最关键的问题:

如果所有东西都需要验证,那第一个东西靠什么验证?

答案:

Trust Anchor

Resolver 本地预先配置 Root 的可信 key。

例如:

Recursive Resolver
│
│ local configuration
▼
Root Trust Anchor

这不是通过普通 DNS 查询得到以后才相信。

而是:

configured locally

所以逻辑是:

TRUST ANCHOR
│
▼
Root DNSKEY
│
▼
DS(.com)
│
▼
.com DNSKEY
│
▼
DS(google.com)
│
▼
google.com DNSKEY
│
▼
A + RRSIG

这就是整个系统的信任起点。

ICANN 将 root KSK 的 public key 作为 DNSSEC 的 root trust anchor;验证器利用它开始建立后续的 chain of trust。

  1. KSK 和 ZSK 又是什么?

这里又会遇到两个概念:

KSK
ZSK

分别是:

KSK

Key Signing Key

主要用来签署:

DNSKEY RRset
ZSK

Zone Signing Key

主要用来签署 zone 中其他 RRsets。

简化理解:

KSK
│
▼
DNSKEY RRset
│
▼
ZSK
│
┌───────┼────────┐
▼ ▼ ▼
A MX TXT
│ │ │
RRSIG RRSIG RRSIG

实际 DNSSEC 的 key-management 会更复杂,但这个模型对于理解 validation 非常有用。

  1. 现在真正走一遍 google.com

假设:

Client
↓
Recursive Resolver

用户:

dig google.com

Resolver 发现 cache miss。

Step 1:问 Root

Resolver:

google.com A ?

向 Root 查询。

Root 不知道:

google.com = ?

但是 Root 知道:

.com authoritative servers

所以返回:

Authority:
.com NS ...

同时 DNSSEC 情况下还有相关签名材料。

  1. Step 2:问 .com

Resolver:

google.com A ?

问 .com authoritative server。

.com 也不知道:

google.com A = ?

但它知道:

google.com authoritative servers

所以返回:

google.com NS ...

并且 DNSSEC 下:

google.com DS ...
RRSIG(DS)

注意这里非常重要:

.com 不仅告诉 resolver:

“Google 的 authoritative DNS 在这里。”

还告诉它:

“这是 Google DNSSEC key 的可信 fingerprint。”

  1. Step 3:问 Google Authoritative DNS

Resolver 去:

google.com authoritative server

查询:

google.com A

得到:

A
RRSIG(A)

同时 resolver 还需要:

google.com DNSKEY
RRSIG(DNSKEY)
13. Resolver 开始验证

现在 resolver 手里有:

Root trust anchor
.com DS
.com DNSKEY
google.com DS
google.com DNSKEY
google.com A
RRSIG(A)

开始:

验证 Root
Trust Anchor
↓
Root DNSKEY

↓

验证 .com
Root
│
└── DS(.com)
↓
.com DNSKEY

↓

验证 google.com
.com
│
└── DS(google.com)
↓
google.com DNSKEY

↓

验证 A record
google.com DNSKEY
+
google.com A
+
RRSIG(A)
↓
VALID

整个过程可以画成:

TRUST ANCHOR
│
▼
Root DNSKEY
│
verify DS
│
▼
.com DNSKEY
│
verify DS
│
▼
google.com DNSKEY
│
verify RRSIG
│
▼
google.com A
│
▼
VALID

BIND 的官方 DNSSEC guide 给出的 validation 流程也是从 child DNSKEY 一直向 parent 查询 DS,再到 Root DNSKEY,最后用本地 trust anchor 判断 Root key 是否可信。

  1. dig 直接观察 DNSSEC

现在我们开始真正操作。

先:

dig google.com

然后:

dig +dnssec google.com

你会看到类似:

;; flags: qr rd ra;

;; ANSWER SECTION:
google.com. 300 IN A 142.250.x.x

google.com. 300 IN RRSIG A ...

重点:

A
RRSIG
15. 查看 DNSKEY

运行:

dig +dnssec google.com DNSKEY

你会看到:

DNSKEY
RRSIG DNSKEY

大概结构:

google.com. IN DNSKEY ...
google.com. IN DNSKEY ...

google.com. IN RRSIG DNSKEY ...

这里的 DNSKEY RRset 本身也需要验证。

这就是为什么你会看到:

DNSKEY
+
RRSIG(DNSKEY)
16. 查看 DS

运行:

dig +dnssec google.com DS

这里查询的是:

google.com DS

但这个 record 实际上位于:

.com zone

所以你可以把它理解成:

.com

google.com. DS ...

它连接:

.com
↓
google.com DNSKEY
17. 这三个命令非常重要

建议你自己运行:

dig +dnssec google.com A
dig +dnssec google.com DNSKEY
dig +dnssec google.com DS

然后把它们放在一起:

A
│
└── RRSIG(A)
↑
│
DNSKEY
↑
│
DS
↑
│
Parent

这时候 DNSSEC 的结构就基本进入脑子了。

  1. delv 更有意思

如果你的系统安装了 BIND utilities,可以试:

delv google.com

delv 和 dig 有一个重要区别:

delv 本身就是为了 DNSSEC validation 而设计的。

BIND 文档说明,delv 默认会进行 DNSSEC validation,并使用 Root zone 的内置 trust anchor;它还可以显示验证相关信息。

所以:

dig

更像:

“让我看看 DNS 返回了什么。”

而:

delv

更像:

“让我验证这些 DNS 数据到底可信不可信。”

  1. DNSSEC 验证失败会发生什么?

这是面试里非常重要的问题。

假设攻击者伪造:

google.com A 6.6.6.6

但对应:

RRSIG

验证失败。

Resolver:

DNSSEC validation
│
▼
INVALID
│
▼
SERVFAIL

所以客户端可能看到:

SERVFAIL

而不是:

6.6.6.6

这也是为什么 DNSSEC validation 能防止某些 DNS spoofing / tampering 场景。ICANN 将 DNSSEC validation 描述为检查 DNS 数据真实性和完整性的机制。

  1. 那 NXDOMAIN 怎么办?

这是 DNSSEC 更厉害的一部分。

攻击者不只是可以伪造:

google.com → fake IP

还可能试图伪造:

doesnotexist.google.com → NXDOMAIN

DNSSEC 需要能够证明:

这个名字真的不存在。

于是出现:

NSEC

或者:

NSEC3

它们提供:

Proof of Non-Existence

也就是说:

普通 DNS:

"没有这个 domain"

DNSSEC:

"我不仅说没有,
我还给你密码学证据证明它不存在。"
21. DNSSEC ≠ DNS Encryption

这个非常容易混。

DNSSEC

解决:

Authenticity
Integrity

即:

DNS answer 是不是可信的?有没有被篡改?

但是 DNSSEC:

不负责加密 DNS query。

DoH / DoT

解决的是:

Privacy / Transport Encryption

例如:

DNS over HTTPS
DNS over TLS

它们保护:

Client
│
│ encrypted
▼
DNS Resolver

所以:

DNSSEC
↓
"答案是真的"

DoH / DoT
↓
"别人不容易看到/修改我和 resolver 之间的 DNS traffic"

两者解决的问题不同。

  1. 最终把整个 DNS + DNSSEC 合起来

现在我们终于可以把前面所有知识串起来:

Browser
│
▼
Browser DNS Cache
│
▼
OS DNS Cache
│
▼
Local DNS / Stub Resolver
│
▼
Recursive Resolver
│
│
├──────────► Root
│ │
│ ▼
│ .com
│ │
│ ▼
│ google.com Auth
│ │
│ ▼
│ A + RRSIG
│
▼
DNSSEC Validation
│
├── Root Trust Anchor
├── DS
├── DNSKEY
├── RRSIG
└── NSEC/NSEC3
│
▼
VALID
│
▼
IP Address
│
▼
TCP / QUIC
│
▼
TLS
│
▼
HTTPS

DNS resolution 告诉你:

google.com → IP

DNSSEC validation 告诉你:

这个 IP 的 DNS 数据
可以通过从 Root 开始的密码学信任链验证。
23. 还有一个非常有意思的现实问题

你现在可以把 DNSSEC 想成:

Root KSK
↓
.com
↓
google.com
↓
A record

但现实世界里 Root KSK 本身也会 rollover(更换)。

而且这是当前真实的 DNS 基础设施事件:ICANN 已公布 2026 年 10 月 11 日进行 Root Zone KSK rollover,新的 KSK-2024 key tag 是 38696;DNSSEC-validating resolver operators 需要确保新的 trust anchor 已正确配置。

所以你现在学到的:

Trust Anchor
     ↓
KSK
     ↓
Chain of Trust

并不是纯理论,而是整个 Internet DNS 基础设施目前正在实际维护的东西。

posted @ 2026-09-12 17:44  JacobJacob  阅读(36)  评论(0)    收藏  举报