4. DNS协议深度分析:递归与迭代查询、DNS缓存投毒、EDNS0扩展

DNS,说白了就是互联网的电话本。你输入一个域名,它帮你找到对应的IP地址。听起来简单,但里面的门道可不少。我做了这么多年网络排障,DNS问题占了至少三成。今天咱们就把它彻底聊透。

4.1 递归查询 vs 迭代查询

这两种查询方式,是DNS工作的核心逻辑。很多朋友分不清,其实看一次抓包就懂了。

4.1.1 递归查询

客户端发一个请求给DNS服务器,说:“帮我查一下 www.example.com 的IP。” 服务器要么返回结果,要么返回错误。它不会让你再去问别人——这就是递归。

我习惯把递归查询比作「甩手掌柜」。你只管把问题丢出去,等着拿答案就行。中间它问了谁、查了几个服务器,你一概不知。

关键特征:

  • 客户端只发一次请求
  • 服务器必须返回最终结果
  • 通常用于客户端到本地DNS服务器

4.1.2 迭代查询

迭代查询就不一样了。服务器告诉你:“我不知道,但你可以去问别人。” 然后给你一个 referral(指引)。

举个例子。你问本地DNS服务器:“www.example.com 在哪?” 它说:“我不知道,你去问根服务器。” 你问根服务器,它说:“去问 .com 顶级域服务器。” 你问 .com 服务器,它说:“去问 example.com 的权威服务器。” 最后你问权威服务器,拿到IP。

你看,每一步都是「你」在主动问。服务器只负责指路,不帮你跑腿。

对比项 递归查询 迭代查询
客户端工作量 低(只发一次) 高(多次请求)
服务器负载 高(要查到底) 低(只给指引)
典型场景 客户端 → 递归器 递归器 → 权威服务器
抓包特征 单次查询 + 单次响应 多次查询 + 多次 referral

4.1.3 Wireshark中怎么看

打开Wireshark,过滤 dns。你会看到两种模式:

  • 递归查询:Flags字段中 Recursion Desired (RD) 位为1,Recursion Available (RA) 位也为1。
  • 迭代查询:响应中不包含答案,而是包含 Authority 和 Additional 记录——这就是 referral。
# 递归查询抓包示例
No.  Time     Source        Destination   Protocol Info
1    0.000    192.168.1.2   8.8.8.8       DNS     Standard query 0x1234 A www.example.com
2    0.045    8.8.8.8       192.168.1.2   DNS     Standard query response 0x1234 A 93.184.216.34

# 迭代查询抓包示例(referral)
No.  Time     Source        Destination   Protocol Info
1    0.000    192.168.1.2   198.41.0.4    DNS     Standard query 0x5678 A www.example.com
2    0.030    198.41.0.4    192.168.1.2   DNS     Standard query response 0x5678 - No such name
      Authority: .  NS a.root-servers.net
      Additional: a.root-servers.net  A 198.41.0.4

嗯,这里要注意。如果你看到响应里没有 Answer RRs,但 Authority 和 Additional 有内容——那就是 referral,典型的迭代查询。

4.2 DNS缓存投毒

这是DNS领域最危险的攻击之一。我当年在ISP干的时候,遇到过一起大规模断网事件,最后定位就是缓存投毒。

4.2.1 原理是什么

攻击者伪造DNS响应,往递归服务器里塞入错误的记录。用户访问正常网站,却被指向钓鱼服务器。

说白了,就是让DNS服务器「记住」错误的信息。下次有人问,服务器直接返回假的IP。

我曾经踩过的坑: 有一次客户反馈访问银行网站跳转到赌博页面。我查了半天,发现是本地路由器上的DNS被篡改了。攻击者利用UPnP漏洞,把路由器的DNS服务器地址改成了恶意服务器。从那以后,我所有项目的第一件事就是锁死DNS配置。

4.2.2 攻击手法

  1. ID欺骗:DNS查询的Transaction ID是16位,只有65536种可能。攻击者批量发送伪造响应,总有一个ID能对上。
  2. 端口随机化绕过:现代DNS服务器使用随机源端口。攻击者需要同时猜对ID和端口,难度大增。
  3. Kaminsky攻击:2008年Dan Kaminsky发现的经典漏洞。攻击者不直接投毒目标域名,而是投毒NS记录,把整个域的查询都引向恶意服务器。
攻击类型 难度 影响范围 防御手段
ID欺骗 低 单个域名 随机源端口
端口随机化绕过 中 单个域名 DNSSEC
Kaminsky攻击 高 整个域 DNSSEC + 源端口随机化

4.2.3 Wireshark检测方法

你可以在Wireshark里设置过滤条件:

# 检测可疑的DNS响应
dns.flags.response == 1 and dns.count.answers > 0 and not dns.flags.authentic_data

# 检测多个相同查询的响应(可能是暴力攻击)
dns.qry.name == "www.example.com" and dns.flags.response == 1

我个人习惯的做法是:先看响应时间。正常DNS响应一般在50ms以内。如果某个响应时间异常短(比如1ms),而且来自非权威源——那就要警惕了。

避坑指南: 我曾经在分析一起投毒事件时,发现攻击者伪造的TTL设得特别大(86400秒)。这样即使发现投毒,缓存也要一天才能过期。所以我现在看DNS抓包,第一眼就看TTL。异常大的TTL + 非权威源 = 大概率有问题。

4.3 EDNS0扩展

EDNS0,全称是Extension Mechanisms for DNS。你想想看,最初的DNS协议是1987年设计的,那时候谁能想到今天的互联网规模?

4.3.1 为什么需要EDNS0

传统DNS报文有512字节的限制。这在80年代够用,但现在一个DNSSEC记录就能轻松超过这个数。EDNS0通过OPT伪资源记录,扩展了UDP报文大小,支持到4096字节甚至更大。

说白了,就是给DNS协议「打补丁」。不改核心协议,但增加扩展能力。

4.3.2 EDNS0的核心能力

  • UDP报文大小扩展:从512字节扩展到4096字节
  • DNSSEC支持:携带DNSSEC相关的OK位和签名记录
  • 客户端子网(ECS):CDN可以根据客户端IP返回最近的节点
  • DNS Cookie:防止DNS放大攻击和缓存投毒

4.3.3 Wireshark中识别EDNS0

在Wireshark里,EDNS0表现为Additional records中的OPT记录。过滤方法:

# 过滤包含EDNS0的DNS报文
dns.opt

# 查看EDNS0版本
dns.opt.version

# 查看支持的UDP大小
dns.opt.udp_payload_size

抓包示例:

Domain Name System (response)
  Transaction ID: 0x9abc
  Flags: 0x8180 Standard query response, No error
  Questions: 1
  Answer RRs: 1
  Authority RRs: 0
  Additional RRs: 1
  Additional records
    <Root>: type OPT (41)
      Name: <Root>
      Type: OPT (41)
      UDP payload size: 4096
      Extended RCODE: 0
      Version: 0
      Flags: 0x00
      Data: 00

4.3.4 实际项目中的坑

我记得有一次,客户说某些地区的用户访问网站特别慢。我抓包一看,发现DNS响应被截断了——中间防火墙把超过512字节的UDP报文直接丢了。

EDNS0虽然支持大报文,但很多老旧设备不支持。解决方案有两个:

  1. 在DNS服务器上强制使用TCP回退(当响应超过512字节时)
  2. 升级中间网络设备,确保支持EDNS0

注意: 有些防火墙会直接丢弃带有OPT记录的DNS报文。如果你发现某些客户端无法解析域名,先检查中间设备是否支持EDNS0。我建议在DNS服务器上开启EDNS0的日志,记录所有协商失败的情况。

4.4 知识体系总览

下面这张图,把本章的核心逻辑串起来了。你一看就明白:

DNS协议核心知识体系 DNS协议核心知识体系 DNS协议 查询模式 递归查询 迭代查询 安全威胁 缓存投毒 DNSSEC 协议扩展 EDNS0 ECS Wireshark实战要点 • 递归查询:看RD/RA标志位 • 缓存投毒:检查TTL异常 + 非权威源 • EDNS0:过滤 dns.opt,查看UDP payload size

4.5 本章小结

DNS协议看起来简单,但递归与迭代的差异、缓存投毒的危害、EDNS0的扩展能力,每一个都值得深挖。我建议你打开Wireshark,抓一次真实的DNS查询,对照着看一遍。纸上得来终觉浅,绝知此事要躬行。

嗯,今天就到这里。记住:DNS是网络的基础设施,出了问题影响面极大。平时多积累抓包经验,关键时刻才能快速定位。