神奇的Willem

DNS解析完全版小白成长之路

2025/12/11
59
0

我们假设你现在的架构是:你的电脑 -> AdGuard Home (AGH) -> Unbound (递归服务器)

在这个抽象的世界,DNS运用的递归解析。

什么是递归解析,就是分区管理,每个都有自己管理的域名。找不到就问下一个。(跟域名只负责记录个大顶级域名)

更详细内容要看前一篇内容。这里是进阶版。

问题一:递归过程到底是谁在跑?权威把答案给谁?

  1. 谁去跑腿?Unbound(递归服务器) 去跑腿。它不会告诉你的电脑“你自己去找根”,而是它自己默默把活干完。

  2. 权威给谁答案? 权威服务器把答案给 Unbound,Unbound 存到缓存,然后再转交给你的电脑。

详细流程图解(以查询 example.com 为例):

  1. 发起请求:你的电脑问 Unbound:“example.com 的 IP 是多少?”(这时候电脑就挂起了,等着要结果)。

  2. Unbound 检查缓存:没有。

  3. Unbound 问根(Root):Unbound 自己发包给根服务器:“你知道 example.com 吗?”

    • 注意:这里不是你的电脑问的,是 Unbound 问的。

  4. 根的回复:根服务器说:“我不知道具体的 IP,但 .comGTLD 服务器 管,你去问它吧(给你 .com 服务器的 IP)。”

  5. Unbound 问 TLD:Unbound 再去问 .com 服务器:“你知道 example.com 吗?”

  6. TLD 的回复.com 服务器说:“我知道,这个域名归 Cloudflare 管,你去问 Cloudflare 吧(给你 Cloudflare 的 IP)。”

  7. Unbound 问权威(Auth):Unbound 最后去问 Cloudflare:“快告诉我 example.com 的 IP!”

  8. 权威的回复:Cloudflare 说:“查到了,IP 是 1.2.3.4。” (答案是给 Unbound 的)

  9. 最终交付:Unbound 收到 1.2.3.4先存入缓存,然后回头告诉你的电脑:“让你久等了,IP 是 1.2.3.4。”

总结: 在整个过程中,你的电脑(客户端)只发了一次请求,收了一次结果。中间那堆累活全是 Unbound 干的。

总结:你发起一个请求,都是运营商dns干的活活着阿里腾讯公共递归解析干的活。来分担跟域名的压力和缓存。

问题二:如果递归服务器有缓存且在有效期内?

简短回答: 直接给你。

详细说明: 如果 Unbound 发现缓存里有 example.com 的记录,且 TTL(生存时间)还没过期:

  1. 你的电脑问 Unbound。

  2. Unbound 还没来得及向外发包,就发现口袋里有答案。

  3. Unbound 立刻、直接把 IP 返回给你的电脑。

  4. 耗时:通常小于 1ms(局域网内)。

  5. 根/权威服务器状态:它们完全不知道这次查询发生过。

总结:如果递归服务器知道,直接返回,包括本地缓存,这涉及到DNS投毒与中间人的问题。包括运营商返回IP不正确或为空。

问题三:关于腾讯注册、CF 解析、阿里子域名的复杂套娃

这个场景非常经典,我称之为顶级套娃。

1. 基础环境

  • 域名注册商:腾讯(DNSPod)。

  • 主域名权威 DNS:Cloudflare。

  • 子域名权威 DNS:阿里云(AliDNS)。

2. “换了 DNS1 和 DNS2 的地址换的是什么地址?”

当你在腾讯的控制台,把 DNS 服务器修改为 ns1.cloudflare.comns2.cloudflare.com 时:

  • 你改的是什么? 你修改的是 TLD(顶级域,即 .com)服务器里的 NS 记录

  • 发生了什么? 腾讯作为注册商,会通知 Verisign(管理 .com 的机构):

    “以后谁查 你的域名.com,别问我了,去问 Cloudflare。”

  • 结果:现在,Cloudflare 成了你域名的大管家(权威服务器)。全世界要查你的域名,最终都会找到 Cloudflare 头上。

总结:注册商声明,告诉顶级域名服务器,以后这个一级域名不要找我,我给你新的,在这段时间内归他管!

问题4:子域名通过 NS 解析到了阿里,NS 解析地址有什么

你在 Cloudflare 的后台,添加了一条记录: sub.你的域名.com 类型 NSns1.alidns.com

  • 这叫什么? 这叫 “子域委派 (Zone Delegation)”

  • NS 解析地址有什么? 这条记录存储在 Cloudflare 的服务器上。

  • 含义:它相当于一个路牌。Cloudflare 告诉来访者:“主域名归我管,但是 sub 这个子部门已经分家出去了,归阿里云管,你们去问阿里云,别问我。”

这个被解析的二级域名又是怎么查询的?

假设你的 Unbound 要查询 sub.你的域名.com,流程如下:

  1. Unbound -> 根:找 .com

  2. Unbound -> .com:找 你的域名.com

  3. .com 服务器:返回 Cloudflare 的 IP(因为它只认大管家)。

  4. Unbound -> Cloudflare(关键点):

    • Unbound 问:“请告诉我 sub.你的域名.com 的 IP。”

    • Cloudflare 查表发现那是条 NS 记录

    • Cloudflare 回答:“我没有它的 IP,因为我把它外包给 阿里云 了。阿里云的 DNS 服务器地址是 ns1.alidns.com,你去问它。”

  5. Unbound -> 阿里云

    • Unbound 问:“Cloudflare 说 sub 归你管,请问它的 IP 是多少?”

    • 阿里云(它手里有真正的 A 记录)回答:“IP 是 8.8.8.8。”

  6. Unbound -> 你的电脑:返回 8.8.8.8

角色

负责范围

对查询者的回应

根 / .com

全球索引

“去找 Cloudflare

Cloudflare

主域名 (a.com, www.a.com)

知道主域 IP 就直接给 IP;


遇到 sub 就说 “去找阿里云”

阿里云

子域名 (sub.a.com)

“IP 是这个!”(最终答案)

总结,还是访问cloudflear,可是cloudflear告诉他其实被分出去了,再让你找下一个阿里云!!!!最后阿里云给递归服务器返回真正的

在dns优化可以直接把整个域名托管,来减少查询中的一环,可以减少一点的时间。

CNAME解析究极无敌套娃中娃

我解析的是cname域名在阿里云上,这是指向的另一个顶级域名,比如我们查询a.aaa.com,结果他指向了一个cname,b.bbb.cc。b.bbb.cc注册商在cloudflear,被托管到华为dns域了。这个查询是怎么查询的呢?

这是一个非常经典的**“跨域 CNAME 跳转”**场景。这个过程之所以有趣,是因为递归服务器(Unbound)需要在两个完全不同的域名树(.com 树和 .cc 树)之间“反复横跳”。

我们将你的场景具体化:

  • 请求域名a.aaa.com

  • 第一跳(CNAME):阿里云 DNS(指向 b.bbb.cc

  • 第二跳(目标)b.bbb.cc

  • 目标归属:注册商是 Cloudflare,但权威 DNS 是华为云

以下是 Unbound 视角的完整查询录(假设无缓存):

第一阶段:(查询 a.aaa.com

  1. Unbound -> 根服务器: “谁管 .com?”

    • 根回复:“去问 .com TLD 服务器。”

  2. Unbound -> .com 服务器: “谁管 aaa.com?”

    • .com 回复:“去问阿里云 DNS(AliDNS)。”

  3. Unbound -> 阿里云 DNS: “请告诉我 a.aaa.com 的 IP。”

  4. 阿里云 DNS(关键点): 它查表发现这是个 CNAME,于是回复:

    我没有 IPa.aaa.com 只是个别名,它的真名(Canonical Name)叫 b.bbb.cc。你去找它吧,我不负责了。”

第二阶段:(查询 b.bbb.cc

此时,Unbound 拿到的是一个域名,而不是 IP。它必须触发内部的“CNAME Restart”逻辑,把 b.bbb.cc 当作一个新的任务,从头开始查。

这里有一个容易混淆的点:Cloudflare(注册商)在这个查询过程中是不出场的。注册商的作用仅仅是在 .cc 的数据库里登记:“bbb.cc 的 DNS 服务器是华为云”。

  1. Unbound -> 根服务器(如果缓存里没有 .cc 的位置): “谁管 .cc?”

    • 根回复:“去问 .cc TLD 服务器。”

  2. Unbound -> .cc TLD 服务器: “谁管 bbb.cc?”

    • .cc 服务器查库(这个库是注册商 Cloudflare 之前写入的),回复:

    “归 华为云 DNS 管。地址是 ns1.hwclouds-dns.com。”

    • 注意:这里完全跳过了 Cloudflare 的服务器。

  3. Unbound -> 华为云 DNS: “既然你管这事,快告诉我 b.bbb.cc 的 IP 到底是多少?”

  4. 华为云 DNS: 查到了 A 记录,回复:

    “IP 是 1.1.1.1。”递归服务器和递归解析

每当用户在浏览器窗口中键入域名(例如“ cloudflare.com”)时,都会触发DNS查找。然后,一系列称为DNS服务器的远程计算机找到该域的IP地址,并将其返回给用户的计算机,以便他们可以访问正确的网站。

几种不同类型的 DNS 服务器必须协同工作才能完成 DNS 查找。DNS 解析器、DNS 根服务器、DNS TLD 顶级域名服务器和 DNS 权威名称服务器都必须提供信息以完成查找。在缓存情况下,这些服务器之一可能已在先前的查找过程中保存了查询的答案,可以将其从内存中传递出来。

总结:查到后直接甩锅重新查询!在改怎么走怎么走

递归DNS的缺点是什么?

不幸的是,在开放的 DNS 服务器上允许递归 DNS 查询会造成安全漏洞,因为此配置可使攻击者执行 DNS 放大攻击和 DNS 缓存中毒。

DNS 缓存中毒?

DNS 缓存投毒是指向 DNS 缓存中输入错误信息的行为,以便使 DNS 查询返回错误响应并将用户定向到错误网站。DNS 缓存投毒也称为“DNS 欺骗”。IP 地址是互联网的“电话号码”,它能够使网络流量到达正确的位置。DNS 解析器缓存类似于“通讯录”,其中会列出所有电话号码以及它们存储错误信息的时间,在缓存的信息得到更正之前,流量将会传输到错误的位置。(请注意,这实际上并未断开真实网站与相应的真实 IP 地址之间的连接。)

因为 DNS 解析器通常无法验证其缓存中的数据,因此错误 DNS 信息会保留在缓存中,直到生存时间(TTL)到期或手动将其移除为止。许多漏洞可能使 DNS 中毒,但主要问题是 DNS 是为远远更小的 Internet 构建的,并且基于信任原则(非常类似于 BGP)。一种更安全的 DNS 协议称为 DNSSEC,其旨在解决其中的一些问题,但尚未得到广泛采用。

DNS 欺骗和审查

多个政府有意在其国家/地区中使 DNS 缓存中毒,以便拒绝对特定网站或网络资源的访问。

DNSSEC 如何帮助防止 DNS 中毒?

DNSSEC 是 Domain Name System Security Extensions 的简称,这是一种验证 DNS 数据完整性和来源的方法。DNS 在最初设计时没有此类验证,这就是 DNS 有可能中毒的原因。

与 TLS/SSL 非常类似,DNSSEC 使用公钥加密(对信息进行数字签名的方式)来核实和验证数据。DNSSEC 扩展发布于 2005 年,但 DNSSEC 尚未成为主流,这使得 DNS 仍然容易受到攻击。

什么是 DNS 放大攻击?

这种 DDoS 攻击是基于反射的大规模分布式拒绝服务 (DDoS) 攻击,其中,攻击者利用开放 DNS 解析器的功能产生大量流量,使目标服务器或网络不堪重负,导致服务器及其周围基础设施无法访问。为借刀杀人,因为你请求的DNS请求数据包很小,一些大的域名他说解析的很多,比如dig -a,他会返回数据是你提交数据的4-5倍。这就是放大攻击。

DNS 放大攻击的工作原理是什么?

所有放大攻击都利用攻击者与目标 Web 资源之间的带宽消耗差异。当消耗差异经过多次请求而被放大时,生成的流量可能会导致网络基础设施中断。通过发送小型请求来导致大规模响应,恶意用户能达到事半功倍的效果。当通过某个僵尸网络中的每个机器人发出类似请求来成倍放大这种效果时,攻击者既能躲避检测,又能收获攻击流量显著增加的好处。

在 DNS 放大攻击中,其中一个机器人好比是一个心怀恶意的青少年打电话给一家餐厅,说“我要每样东西点一份,请给我回电话,告诉我整个订单”。当餐厅询问回电号码时,提供的是目标受害者的电话号码。然后目标会接到来自餐厅的电话,提供其并未请求的大量信息。

由于每个自动程序向开放 DNS 解析器提出请求时都提供欺骗性 IP 地址,也就是目标受害者的真实源 IP 地址,目标随后会收到来自 DNS 解析器的响应。为了产生大量流量,攻击者会以某种方式来构造请求,以便让 DNS 解析器产生尽可能大的响应。因此,目标接收攻击者的初始流量的放大结果,其网络被虚假流量堵塞,导致拒绝服务。

什么是 DNS NS 记录?

NS 代表“域名服务器”,域名服务器记录指示哪个 DNS 服务器对该域具有权威性(即,哪个服务器包含实际 DNS 记录)。基本上,NS 记录告诉互联网可从哪里找到域的 IP 地址。一个域通常会有多个 NS 记录,这些记录可指示该域的主要和辅助域名服务器。倘若没有正确配置的 NS 记录,用户将无法加载网站或应用程序。下面是一个 NS 记录示例:

example.com

record type:

value:

TTL

@

NS

ns1.exampleserver.com

21600

请注意,NS 记录永远不能指向规范名称(CNAME)记录。

什么是 DNS MX 记录?(均来自于cloudflare)

DNS“邮件交换”(MX) 记录将电子邮件定向到邮件服务器。MX 记录指示如何根据简单邮件传输协议(SMTP,所有电子邮件的标准协议)路由电子邮件消息。

MX 记录示例:

example.com

record type:

优先级:

value:

TTL

@

MX

10

mailhost1.example.com

45000

@

MX

20

mailhost2.example.com

45000

这些 MX 记录的前面的“优先级”数字表示优先权,较低的“优先级”值是首选。服务器将始终先尝试 mailhost1,因为 10 小于 20。当消息发送失败时,服务器将默认使用 mailhost2。

电子邮件服务也可以配置该 MX 记录,使两个服务器有同等的优先级,并收到同等数量的邮件:

example.com

record type:

优先级:

value:

TTL

@

MX

10

mailhost1.example.com

45000

@

MX

10

mailhost2.example.com

45000

这种配置使电子邮件提供商能够平等地在两个服务器之间平衡负载

什么是 DNS TXT 记录?

DNS“文本”(TXT) 记录允许管理员将文本输入到域名系统 (DNS) 中。文本以一个或多个用引号引起来的字符串的形式存储。TXT 记录最初的目的是用作存放人类可读笔记的地方。但是,现在也可以将一些机器可读的数据放入 TXT 记录中。一个域可以有许多 TXT 记录。

TXT 记录示例:

example.com

record type:

value:

TTL

@

TXT

“这是一个很棒的域名!绝对不是垃圾邮件。”

32600

如今,DNS TXT 记录的两个最重要用途是防止垃圾邮件和域名所有权验证,尽管 TXT 记录最初并非为这些用途而设计。

什么样的数据可以放在 TXT 记录中?

原始 RFC 仅指出“文本字符串”要放在 TXT 记录的“value”字段中。这可以是管理员想要与他们的域名相关联的任何文本。

大多数 DNS 服务器会对 TXT 记录的大小和可存储字串的数量进行限制,所以管理员无法使用 TXT 记录来存储大量数据。

字符串限制为 255 个字节,但应用通常不关心字符串之间的区别,而只是将它们连接在一起,将多个字符串视为一个字符串。

TXT 记录如何帮助防止垃圾邮件?

垃圾邮件发送者经常试图伪造或假冒他们发送电子邮件的域。TXT 记录是几种不同的电子邮件验证方法的关键组成部分,它可帮助电子邮件服务器确定邮件是否来自可信的来源。

常见的电子邮件身份验证方法包括域密钥识别邮件 (DKIM)、发送方策略框架 (SPF) 以及基于域的邮件身份验证、报告和一致性 (DMARC)。通过配置这些记录,域运营商可以使垃圾邮件发送者更难伪造他们的域,并且可以跟踪此类尝试。

SPF 记录:SPF TXT 记录列出了所有被授权从一个域发送电子邮件的服务器。

DKIM 记录:DKIM 的工作原理是使用一个公钥-私钥对,对每封电子邮件进行数字签名。这有助于验证电子邮件确实来自它所声称的域。公钥被存放在与域关联的 TXT 记录中。(了解有关公钥加密的更多信息)。

DMARC 记录:DMARC TXT 记录引用域的 SPF 和 DKIM 政策。它应该存储在标题 _marc.example.com 下,“example.com”用实际域名代替。记录的“值”是域的 DMARC 政策(可在此处找到创建该政策的指南)。

TXT 记录如何帮助验证域所有权?(重要)

虽然域所有权验证最初不是 TXT 记录的一个功能,但这种方法已经被一些网站管理员工具和提供商采用。

管理员可以通过上传包含特定信息的新 TXT 记录,或编辑当前的 TXT 记录,来证明他们控制着该域。工具或云提供商可以检查 TXT 记录,并看到它已按要求进行了更改。这有点像用户通过打开并点击发送到该电子邮件的链接来确认其电子邮件地址,证明他们拥有该地址。

深入了解不同类型的 DNS 记录

重要:申请 SSL 证书 (Let's Encrypt) 当你申请通配符证书(*.你的域名.com)时,Certbot 会让你加一条 _acme-challenge 的 TXT 记录,证明域名归你管。

SOA 记录 (Start of Authority)

它是干啥的? 这是 DNS 区域的“出生证明”和“管理档案”。 每一个域名(比如 baidu.com),必须要有一个 SOA 记录。它定义了这个域名的:

  • 版本号 (Serial Number):比如 2023121101。每次修改 DNS 记录,这个号必须变大。递归服务器看到号码变了,就知道“哦,有新数据了”。

  • 刷新时间 (Refresh):告诉从属服务器多久来查一次岗。

  • 管理员邮箱

写入有用吗?

  • 对你没用:在使用阿里云、Cloudflare 解析时,它们会自动帮你生成和维护 SOA 记录。你根本无法(也不需要)手动修改它。

  • 场景:除非你自己用 BIND 软件搭建一个权威 DNS 服务器(而不是现在的递归),否则你永远不用碰它。

1. 刷新时间 (Refresh): 1800 (30分钟) —— 根服务器内部的同步节奏

  • 含义:这是给辅根服务器(Slave Servers)看的。

  • 背景:全球有 13 个根(A-M),其中 A 是主根(Hidden Primary),其他的是镜像。

  • 作用:这个 1800 告诉其他的根服务器:“兄弟们,每隔 30分钟 来检查一下我的序列号变没变。如果变了,赶紧把新数据拉过去。”

  • 对你的影响几乎为零。这是它们神仙打架(服务器同步)的事,跟你的 Unbound 没关系。

2. 最小 TTL (Minimum TTL): 86400 (1天)(重要)

这是 SOA 记录里对你的递归服务器(Unbound)影响最大的一个值。

它控制的是 “否定缓存(Negative Caching)” 的时间。

  • 场景: 假设你手滑了,查询了一个根本不存在的顶级域,比如 test.hahaha。 Unbound 去问根服务器:“.hahaha 这个顶级域归谁管?” 根服务器说:“NXDOMAIN(查无此人),滚犊子。”

  • 关键点: 根服务器不仅会告诉你“没有”,还会附上这个 SOA 记录。 你的 Unbound 看到最后那个数字 86400,就会在心里记下:

    “根老大说了,.hahaha 是不存在的。接下来的 1天(86400秒) 内,如果再有人问我 .hahaha,我直接告诉他没有,绝不再去骚扰根服务器。”

总结: 如果你问的“刷新时间”是指**“根服务器更新了新的顶级域,我的 Unbound 多久能知道?”**

重点:SRV 记录 (Service)

它是干啥的? 普通的 A 记录只告诉对方 IP 是多少,默认端口大家心照不宣(Web 就是 80/443)。 但如果你的服务跑在非标准端口上呢?SRV 就是告诉客户端: “你要找的服务(Service)在某台机器(Target)的 某个端口(Port)上。”

格式长这样: _minecraft._tcp.example.com -> SRV 10 5 25565 mc.example.com 意思是:想玩 Minecraft?去 mc.example.com25565 端口。

我们平时能用到吗? 非常有用! 如果你玩自托管(Self-hosting),SRV 是神器。

  • 场景 1:Minecraft 服务器 你家里只有一条公网 IP,但你想开好几个服,或者不想让朋友输入丑陋的 1.2.3.4:25565。 配置 SRV 后,朋友只需要输入 mc.你的域名.com,客户端会自动通过 SRV 记录找到背后的 25565 端口。

  • 场景 2:语音服务器 (TeamSpeak / VoIP) SIP 电话和 TeamSpeak 经常使用 SRV 记录来实现自动发现和负载均衡。

  • 场景 3:企业域控 (Active Directory) 如果你在公司内网,Windows 电脑加域全靠 SRV 记录来寻找域控制器。

2. SRV 记录的解剖学 (格式详解)

SRV 记录的格式非常严格,多一个点少一个下划线都不行。

为了让你理解为什么不能省,想象一下 DNS 协议是一张Excel 表格,这一行规定了必须有 7 列数据。 服务 | 协议 | 域名 | 优先级 | 权重 | 端口 | 目标

如果你不填权重和优先级,这行数据就错位了,电脑读到“端口”那一栏时,发现读到的是个空值或者读串行了,整个解析就会失败。

标准格式: _Service._Proto.Name TTL Class SRV Priority Weight Port Target

实战示例 (Minecraft): _minecraft._tcp.play.example.com. 3600 IN SRV 0 5 25565 mc.example.com.

字段逐一解析:

  1. _Service (服务名):

    • 必须以下划线 _ 开头。

    • 标准化的名字,比如 _minecraft (麦块), _ldap (域控), _sip (语音), _xmpp (聊天)。

  2. _Proto (协议):

    • 必须以下划线 _ 开头。

    • 通常是 _tcp_udp

  3. Name (域名):

    • 你提供给用户的域名,比如 play.example.com

  4. Priority (优先级):

    • 数值越小,优先级越高

    • 客户端必须先尝试优先级数值最小的服务器。如果那个挂了,才去试数值大一点的。

    • 用途:实现主备服务器切换。

  5. Weight (权重):

    • 数值越大,负载越高

    • 只有在“优先级”相同时,权重才生效。

    • 如果两台服务器优先级都是 0,一台权重 10,一台权重 90。那么 90% 的请求会去第二台。

    • 用途:实现简单的负载均衡。

  6. Port (端口):

    • 告诉客户端连接哪个端口(例如 25565)。

  7. Target (目标主机):

    • 提供服务的具体服务器域名(例如 mc.example.com)。

    • ⚠️ 核心规则:这里必须指向一个 A 记录AAAA 记录绝对不建议指向 CNAME(虽然某些实现能跑通,但违反规范且效率低)。

你为了防 DDoS 买了个高防 IP,但是高防商只给你开放了 38291 这种随机端口。你想让玩家看着舒服:

  • 用户输入:mc.你的域名.com

  • SRV 记录:_minecraft._tcp.mc SRV 0 5 38291 高防IP的A记录