子域名挖掘前置基础 02:DNS 解析流程(简单版)
本篇定位 :上一篇讲了 URL、域名、IP 这些地基。本篇开始讲 DNS 怎么把域名翻译成 IP。这一篇是简单版------只讲整体流程和关键概念,不展开每一步的输入输出细节。详细版在下一篇单独讲。
一、DNS 服务器的分级:谁是翻译链路上的节点
DNS 不是一台服务器,而是一组分工不同的服务器集群。要理解解析流程,先得认识链路上有哪几种角色。
1.1 四种 DNS 服务器角色
| 角色 | 简称 | 职责 | 类比 |
|---|---|---|---|
| 根域名服务器 | Root | 知道所有顶级域(TLD)的权威服务器在哪 | 总机台 |
| 顶级域服务器 | TLD | 知道该 TLD 下所有二级域的权威服务器在哪 | 部门前台 |
| 权威服务器 | Authoritative | 存着某个域名最终的记录(A、CNAME 等) | 业务办公室 |
| 递归解析器 | Recursive Resolver | 替用户跑完整条链路,把结果返回给用户 | 跑腿员 |
1.2 它们之间的关系
用户浏览器
│
▼
递归解析器 ──问──> 根服务器 ──指路──> TLD服务器 ──指路──> 权威服务器
│ │
│ <───────────── 最终结果 ──────────────────────┘
▼
返回给用户
- 根服务器 :不直接回答"api.example.com 是什么 IP",它只告诉你"去问
.com的 TLD 服务器" - TLD 服务器 :不直接回答 IP,它告诉你"去问
example.com的权威服务器" - 权威服务器 :这才是唯一能给出最终答案 的地方------它存着
api.example.com的 A 记录 - 递归解析器:替用户跑完这条链路,把最终 IP 拿回来交给用户
关键认知 :只有权威服务器能给出最准确、最新的数据。其他服务器要么是指路的,要么是缓存的。这就是为什么子域名挖掘里,对关键子域要直接向权威服务器做验证查询------绕过缓存层,拿到真实状态。
1.3 权威服务器的"权威"是什么意思
"权威"(Authoritative)这个词容易让新手发懵。它的意思很简单------这个服务器是某个域名的最终数据源,该域名下所有记录都以它为准。
example.com的权威服务器(假设是ns1.example.com)存着example.com及其子域(如果未委派)的所有记录- 递归解析器拿到的数据如果和权威服务器不一致,以权威服务器为准
- 权威服务器说"这个子域名不存在",那就是真的不存在
后续讲 Zone Delegation 时会展开:子域可以有自己的独立权威服务器,这时主域权威服务器就不知道子域的细节了------这是委派的核心概念。
二、用户输入 URL 后的解析流程(简单版)
把上面的角色串起来,就是一个完整的解析流程。这里先讲简单版,每一步只说"做了什么",不说输入输出细节。
2.1 简单版流程图
#mermaid-svg-rXII88JXVmZtNCUK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rXII88JXVmZtNCUK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rXII88JXVmZtNCUK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rXII88JXVmZtNCUK .error-icon{fill:#552222;}#mermaid-svg-rXII88JXVmZtNCUK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rXII88JXVmZtNCUK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rXII88JXVmZtNCUK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rXII88JXVmZtNCUK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rXII88JXVmZtNCUK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rXII88JXVmZtNCUK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rXII88JXVmZtNCUK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rXII88JXVmZtNCUK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rXII88JXVmZtNCUK .marker.cross{stroke:#333333;}#mermaid-svg-rXII88JXVmZtNCUK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rXII88JXVmZtNCUK p{margin:0;}#mermaid-svg-rXII88JXVmZtNCUK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rXII88JXVmZtNCUK .cluster-label text{fill:#333;}#mermaid-svg-rXII88JXVmZtNCUK .cluster-label span{color:#333;}#mermaid-svg-rXII88JXVmZtNCUK .cluster-label span p{background-color:transparent;}#mermaid-svg-rXII88JXVmZtNCUK .label text,#mermaid-svg-rXII88JXVmZtNCUK span{fill:#333;color:#333;}#mermaid-svg-rXII88JXVmZtNCUK .node rect,#mermaid-svg-rXII88JXVmZtNCUK .node circle,#mermaid-svg-rXII88JXVmZtNCUK .node ellipse,#mermaid-svg-rXII88JXVmZtNCUK .node polygon,#mermaid-svg-rXII88JXVmZtNCUK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rXII88JXVmZtNCUK .rough-node .label text,#mermaid-svg-rXII88JXVmZtNCUK .node .label text,#mermaid-svg-rXII88JXVmZtNCUK .image-shape .label,#mermaid-svg-rXII88JXVmZtNCUK .icon-shape .label{text-anchor:middle;}#mermaid-svg-rXII88JXVmZtNCUK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rXII88JXVmZtNCUK .rough-node .label,#mermaid-svg-rXII88JXVmZtNCUK .node .label,#mermaid-svg-rXII88JXVmZtNCUK .image-shape .label,#mermaid-svg-rXII88JXVmZtNCUK .icon-shape .label{text-align:center;}#mermaid-svg-rXII88JXVmZtNCUK .node.clickable{cursor:pointer;}#mermaid-svg-rXII88JXVmZtNCUK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rXII88JXVmZtNCUK .arrowheadPath{fill:#333333;}#mermaid-svg-rXII88JXVmZtNCUK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rXII88JXVmZtNCUK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rXII88JXVmZtNCUK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rXII88JXVmZtNCUK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rXII88JXVmZtNCUK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rXII88JXVmZtNCUK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rXII88JXVmZtNCUK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rXII88JXVmZtNCUK .cluster text{fill:#333;}#mermaid-svg-rXII88JXVmZtNCUK .cluster span{color:#333;}#mermaid-svg-rXII88JXVmZtNCUK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rXII88JXVmZtNCUK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rXII88JXVmZtNCUK rect.text{fill:none;stroke-width:0;}#mermaid-svg-rXII88JXVmZtNCUK .icon-shape,#mermaid-svg-rXII88JXVmZtNCUK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rXII88JXVmZtNCUK .icon-shape p,#mermaid-svg-rXII88JXVmZtNCUK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rXII88JXVmZtNCUK .icon-shape .label rect,#mermaid-svg-rXII88JXVmZtNCUK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rXII88JXVmZtNCUK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rXII88JXVmZtNCUK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rXII88JXVmZtNCUK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. 查本地缓存
2. 缓存未命中
3. 查根服务器
4. 查 TLD 服务器
5. 查权威服务器
6. 返回 IP
7. 缓存并返回
用户浏览器
输入 api.example.com
本地 DNS 缓存
(浏览器/操作系统/hosts)
递归解析器
(ISP DNS / 8.8.8.8)
根 DNS 服务器
(. → 返回 .com 的 NS 地址)
.com TLD 服务器
(.com → 返回 example.com 的 NS 地址)
example.com 权威 NS
(ns1.example.com → 返回 api 的 A 记录)
2.2 七步解读
| 步骤 | 做了什么 | 谁在做 |
|---|---|---|
| 1 | 浏览器先查本地缓存,看域名是不是刚查过 | 浏览器/操作系统 |
| 2 | 缓存没命中,把请求转给递归解析器 | 操作系统 |
| 3 | 递归解析器问根服务器".com 在哪" |
递归解析器 |
| 4 | 根返回".com 的 TLD 服务器地址",解析器再去问 TLD |
递归解析器 |
| 5 | TLD 返回"example.com 的权威服务器地址",解析器再去问权威 |
递归解析器 |
| 6 | 权威服务器返回 api.example.com 的 A 记录(IP) |
权威服务器 |
| 7 | 递归解析器把 IP 缓存一份,返回给浏览器 | 递归解析器 |
2.3 从挖掘者视角看这个流程
这个流程教科书都讲,但从挖掘者视角要重新解读每个环节:
| 环节 | 挖掘者要关注什么 |
|---|---|
| 本地缓存 | 你拿到的可能是几小时前的旧数据,不是目标当前的配置 |
| 递归解析器 | 你用 subfinder、httpx 做 DNS 查询时,默认走的就是它------拿到的是缓存数据 |
| 权威 NS | 唯一能保证返回最新、最准确数据的地方,关键子域要直接向它验证 |
| TLD 服务器 | 通过它能拿到目标域名的 NS 记录------是"找到权威 NS"的中间步骤 |
| 缓存机制 | TTL(Time To Live,记录存活时间)决定数据新鲜度,是应该记录的字段 |
关键认知 :递归查询拿到的是缓存数据,迭代查询拿到的是实时数据。对关键子域,直接向目标的权威 NS 做查询验证------这是区分"过期数据"和"真实状态"的方法。
三、迭代和递归:两种查询方式
上面流程里,递归解析器一会"问"根、一会"问"TLD、一会"问"权威------它为什么要跑这么多趟?这就涉及 DNS 查询的两种基本方式:迭代 和递归。
3.1 两种查询方式的区别
| 查询方式 | 谁跑路 | 类比 | 例子 |
|---|---|---|---|
| 递归查询 | 解析器替用户跑完全程 | 用户让跑腿员去买东西,跑腿员自己去跑 | 用户 → 递归解析器 |
| 迭代查询 | 解析器逐级问,每一级只给"下一步该去哪" | 跑腿员问总机台,总机台说"去问部门前台",跑腿员再去 | 递归解析器 → 根 → TLD → 权威 |
3.2 一个例子说清
假设你(用户的浏览器)要查 api.example.com 的 IP:
递归部分(用户 → 递归解析器):
- 用户:帮我查
api.example.com - 递归解析器:好,我去跑
迭代部分(递归解析器逐级问):
- 递归解析器 → 根服务器:
api.example.com在哪? - 根服务器:我不知道最终答案,但
.com归 TLD 管,去问 TLD(给地址) - 递归解析器 → TLD 服务器:
api.example.com在哪? - TLD 服务器:我不知道最终答案,但
example.com归它的权威 NS 管,去问权威(给地址) - 递归解析器 → 权威服务器:
api.example.com在哪? - 权威服务器:这个我知道!IP 是
1.2.3.4
3.3 为什么不全部递归
根服务器和 TLD 服务器为什么不肯直接帮用户跑完,只肯"指路"?原因很简单------它们太忙了。
全球几十亿用户、每秒上亿次 DNS 查询,根服务器和 TLD 服务器如果每个都帮用户跑全程,早就瘫痪了。所以它们只做一件事------指路,让递归解析器自己跑。而递归解析器是专门干这个的,而且会缓存结果,同样的查询只跑一次。
关键认知 :根服务器和 TLD 服务器只做迭代应答(指路),不做递归(帮你跑全程)。递归这件事是递归解析器在干。
四、DNS 的 UDP 查询和 TCP 查询
DNS 查询走的是网络协议。它默认用 UDP(User Datagram Protocol,用户数据报协议,无连接、快、但不保证可靠),但在某些场景下也会用 TCP(Transmission Control Protocol,传输控制协议,有连接、可靠、但慢)。
4.1 UDP 和 TCP 的基本区别
| 特性 | UDP | TCP |
|---|---|---|
| 连接 | 无连接,发完就走 | 三次握手建立连接 |
| 速度 | 快 | 慢 |
| 可靠性 | 不保证到达 | 保证到达、保证顺序 |
| 数据大小 | 单包 ≤ 512 字节(传统) | 可传大数据 |
| 适用场景 | 小查询、要快 | 大响应、区域传送 |
4.2 DNS 什么时候用 UDP,什么时候用 TCP
| 场景 | 用什么 | 原因 |
|---|---|---|
| 普通查询(A 记录等) | UDP | 响应小,要快 |
| 响应超过 512 字节 | TCP | UDP 包放不下 |
| DNSSEC 相关查询 | TCP | 响应大、要可靠 |
| Zone Transfer(区域传送) | TCP | 数据量大、要可靠 |
4.3 对子域名挖掘的意义
关键认知 :DNS 默认走 UDP,且 UDP 是无连接的------这意味着 DNS 查询是非常适合批量、快速做的。子域名字典爆破一次查几千个域名,靠的就是 UDP 的速度。但要注意------UDP 不保证到达,所以爆破工具会做重试机制,避免漏报。
另外,Zone Transfer(AXFR)走 TCP。这意味着如果你想做区域传送(一次性拿整个 Zone 的记录),必须用 TCP------而且大多数权威服务器会拒绝这种请求,除非配置不当。这是后续"主动探测"章节会讲的内容。
五、本地 DNS 与公共 DNS 服务器
前面说"递归解析器"替用户跑完链路。但用户具体用的是哪个递归解析器?这取决于网络配置。常见的有两类------本地 DNS 和公共 DNS。
5.1 本地 DNS 服务器
| 类型 | 说明 | 典型例子 |
|---|---|---|
| 操作系统 DNS | 系统配置的 DNS 服务器 | 由 DHCP 自动下发 |
| 企业内网 DNS | 公司自建的 DNS 服务器 | 内网域名解析、过滤策略 |
| ISP DNS | 运营商提供的 DNS | 电信、联通、移动各自的 DNS |
特点:
- 离用户近,查询快
- 缓存命中率较高
- 但可能被运营商做劫持、过滤、广告注入
5.2 公共 DNS 服务器
| 服务商 | IP | 特点 |
|---|---|---|
| Google Public DNS | 8.8.8.8、8.8.4.4 |
全球通用、稳定 |
| Cloudflare DNS | 1.1.1.1、1.0.0.1 |
注重隐私、快 |
| 阿里 DNS | 223.5.5.5、223.6.6.6 |
国内快 |
| 腾讯 DNSPod | 119.29.29.29 |
国内快 |
| OpenDNS | 208.67.222.222 |
有家庭过滤功能 |
特点:
- 不受运营商劫持影响
- 解析结果相对"干净"
- 但可能因地理位置不同,对 CDN 调度结果有影响
5.3 对子域名挖掘的意义
| 影响点 | 说明 |
|---|---|
| 缓存差异 | 不同递归解析器的缓存不同,可能拿到不同的结果 |
| CDN 调度 | 公共 DNS(如 8.8.8.8)查询 CDN 域名,可能返回离 DNS 服务器近的节点,而不是离你近的 |
| 多 DNS 交叉验证 | 对关键子域,应该用多个递归解析器交叉查询,避免单点缓存偏差 |
关键认知:你用的递归解析器会影响你拿到的结果------尤其是走了 CDN 的子域名。这就是为什么子域名挖掘工具通常会支持指定 DNS 服务器,甚至用多 DNS 交叉验证。
六、本篇小结
| 概念 | 一句话 |
|---|---|
| DNS 服务器分级 | 根、TLD、权威、递归四种角色,各有分工 |
| 简单解析流程 | 浏览器 → 本地缓存 → 递归解析器 → 根 → TLD → 权威 → 返回 |
| 迭代和递归 | 递归是"跑腿员替你跑",迭代是"逐级指路" |
| UDP 和 TCP | 默认 UDP(快、无连接),大响应和区域传送用 TCP |
| 本地与公共 DNS | 用的解析器不同,拿到的结果可能有差异 |
有了这些概念,下一篇我们讲详细版解析流程------把每一步的输入、输出、参与者、缓存行为都展开,并配 mermaid 图。