Wireshark实战:从DNS SERVFAIL到TCP 53端口区域传送故障排查

发布时间:2026/10/6 5:56:55
Wireshark实战:从DNS SERVFAIL到TCP 53端口区域传送故障排查 简介这是《Wireshark数据包分析实战第3版》10.5.2节的案例分析材料面向网络运维人员、协议分析学习者及备考网络认证的读者。案例从分公司工作站访问总部应用服务器失败切入首先看到DNS查询应用服务器A记录却收到服务器故障响应随后捕获到分公司DNS服务器改用TCP与中心办公室DNS服务器的53端口通信但SYN包未被应答。对照书中第7章关于DNS使用TCP条件的讨论可定位到总部与分公司DNS区域传送失败进一步嗅探中心办公室DNS流量后发现SYN包从未到达服务器最终查明是路由器仅允许53端口UDP而阻断TCP的配置错误所致。资源为1个PDF文件大小644KB包含章节全文、Wireshark抓包截图和分步排查说明可作为网络排错实战的补充阅读材料。目前已有326人学习下载。通过学习读者可掌握从DNS响应码、数据包特征到路由器ACL配置逐层验证的方法理解DNS区域传送为何依赖TCP以及如何利用端口镜像与流量捕获判断故障点对提升真实网络环境下的诊断能力很有帮助。1. Wireshark 数据包分析实战一个 DNS 故障案例教你读懂 TCP 与 UDP 的 53 端口之争第一次看到这个案例的抓包文件时我愣了一下——总共只有两个数据包一个 DNS 查询一个服务器故障响应然后就没了。这看起来像是最简单的故障但恰恰是这个只有两个包的捕获文件背后藏着一个跨办公室的网络配置错误。问题的表象是用户打不开总部应用中间层是DNS 查询返回服务器故障而真正的根因是分支办公室 DNS 服务器与总部 DNS 服务器之间的区域传送被路由器拦截了。这篇笔记把这个案例拆开带着你从 workstation 视角一路追到路由器 ACL 配置搞清楚 Wireshark 抓包分析中看到什么、推断什么、验证什么的完整链路。适合刚接触 Wireshark 的运维人员也适合想要把 DNS 协议细节落到实际排障场景的工程师。2. 第一次抓包只有两个数据包怎么锁定 DNS 故障方向2.1 捕获文件里的第一个包从 172.16.16.101 到 172.16.16.251 的 DNS 查询打开捕获文件第一个数据包的时间戳标记了整个故障的起点。工作站 172.16.16.101 想要访问托管在总部的应用服务器 172.16.16.200但客户端首先做的不是直接发起 HTTP 请求而是先发一个 DNS 查询——它需要把应用服务器的域名解析成 IP 地址。这个 DNS 请求的细节值得逐字段看一遍。数据包的目的地址是 172.16.16.251这是分公司本地的 DNS 服务器地址。查询类型是 A 记录查询也就是把域名映射到 IPv4 地址的标准查询。Wireshark 的协议解析树中Domain Name System (query)这一层会清楚显示Queries列表里的名称和类型。如果用的是命令行过滤可以这样直接锁定这个包# 过滤出工作站发出的 DNS 查询请求 tshark -r first_capture.pcap -Y ip.src172.16.16.101 dns.flags.response0 # 只看 DNS 查询中的 A 记录请求 tshark -r first_capture.pcap -Y dns.qry.type1dns.flags.response0表示只匹配请求包而不是响应包dns.qry.type1对应 A 记录的标准类型值。这里要强调一个判断逻辑客户端先问 DNS而不是先连目标 IP说明 172.16.16.101 上配置的是域名访问方式。如果这里看到的是直接发往 172.16.16.200 的 TCP SYN排查方向就完全不同了。2.2 响应的异常服务器故障标志位与实际意义第二个数据包是 DNS 响应但 Wireshark 的解析树里Flags字段显示的不是正常的Standard query response, No error而是Server failure。这个标志位的值为0x0002对应SERVFAIL。SERVFAIL和NXDOMAIN的区别非常重要。NXDOMAIN表示域名本身不存在是权威服务器明确告诉你这个域名查无此记录而SERVFAIL表示 DNS 服务器在尝试解析时遇到了上游问题——它自己也不知道为什么失败但可以肯定不是域名不存在。在这个案例里响应包中没有附带任何 Answer 记录Answers字段为空这进一步验证了查询根本没有被正确解析。下面一段简单的 Python 脚本可以帮你批量分析 pcap 中的 DNS 响应状态码在排查大规模 DNS 故障时非常实用import pyshark cap pyshark.FileCapture(stranded_branchdns.pcap, display_filterdns) for pkt in cap: if hasattr(pkt, dns): dns pkt.dns # dns.flags.rcode 字段对应响应状态码0 为无错误2 为 SERVFAIL rcode getattr(dns, flags_rcode, None) if rcode 2: print(f发现 SERVFAIL 响应数据包编号: {pkt.number})用pyshark的display_filterdns只保留 DNS 流量逐包检查flags_rcode字段的具体取值。这里rcode 2对应的就是SERVFAIL。实际工作中如果你发现大量SERVFAIL而不是NXDOMAIN应该优先怀疑 DNS 服务器到上游权威服务器的链路而不是去检查域名配置。3. 深入捕获从分支 DNS 服务器视角看 TCP 53 端口的 SYN 包3.1 端口镜像调整与 stranded_branchdns.pcap 的采集思路第一轮抓包停在工作站侧只证明了一件事分支的 DNS 服务器 172.16.16.251 向上请求时遇到了问题。但问题出在分支 DNS 服务器本身还是它和总部之间的链路这时需要把嗅探位置从终端侧移动到 DNS 服务器侧。这个案例中调整的是交换机端口镜像设置把原本镜像到工作站网卡的流量改成镜像 DNS 服务器 172.16.16.251 的上联口。注意一个细节嗅探器物理位置不动只改镜像对象。这是排障中很实用的手法——你不需要抱着笔记本跑到机房远程改一下交换机的 SPAN 配置就行。捕获结果保存为stranded_branchdns.pcap打开后能看到之前那两个数据包工作站查询和 SERVFAIL 响应以及额外出现的一个数据包。这个额外数据包才是整个案例的转折点。它显示分支 DNS 服务器尝试与 172.16.16.250 的标准 DNS 端口 53 建立 TCP 连接发起了一个 SYN 包。但这不是普通的 DNS-over-TCP 查询它没有对应的 UDP 查询前置流量——也就是说这不是响应过大导致 fallback 到 TCP的场景。3.2 TCP SYN 包不是 UDPDNS 区域传送的协议特征DNS 默认使用 UDP 53 端口这在绝大多数查询场景下都是正确的。但有例外当响应超过一定大小通常是 512 字节EDNS0 支持更大的 UDP 报文但有些网络环境会限制客户端会切换为 TCP 重试另一种情况就是 DNS 区域传送Zone Transfer。区域传送的目的是让从属 DNS 服务器从主服务器同步整个区域的所有资源记录这个数据量远超单个 UDP 包的承载能力所以必须要走 TCP。这个案例中的 SYN 包正是区域传送的起点。分支 DNS 服务器作为总部的从属服务器需要从 172.16.16.250 拉取资源记录。Wireshark 中可以通过过滤表达式快速识别这类流量# 只看发往 DNS 服务器 53 端口 TCP 端口的 SYN 包 tshark -r stranded_branchdns.pcap -Y tcp.dstport53 tcp.flags.syn1 # 过滤 DNS 区域传送相关的查询类型AXFR 对应 252 tshark -r stranded_branchdns.pcap -Y dns.qry.type252dns.qry.type252是 AXFR 类型也就是标准区域传送请求。实际排查中看到一个 TCP SYN 发往 53 端口时需要先判断它是大响应触发的 fallback还是区域传送。判断依据是时间上下文如果前面紧跟着一个标记为 TCTruncated的 UDP DNS 响应那是 fallback如果没有而是周期的同步行为大概率是区域传送。4. 根因定位路由器 ACL 拦截了 TCP 53 导致区域传送失败4.1 从SYN 无响应推断链路问题的排查路径捕获文件显示 SYN 包发出了但始终没有收到对端的 SYN-ACK 响应。这里 Wireshark 显示的重传次数和 TCP 状态可以帮助判断故障位置。如果只有 SYN 重传而没有对应响应问题通常出在中间链路的防火墙或路由器的 ACL 规则上而不是目标服务器本身——因为服务器如果正常运行会在内核协议栈层面立即响应 SYN。要验证这个推断最直接的手段是在总部 DNS 服务器侧在同一个时间窗口抓包。如果服务器侧能看到 SYN 而没回 SYN-ACK那是服务器本身的问题如果服务器侧连 SYN 都看不到问题在传输链路上。这个案例里笔者没有给出中心办公室 DNS 服务器的捕获文件因为根本没有——SYN 数据包从未到达服务器。实际排查时如果无法快速在两台 DNS 服务器同时抓包可以退一步用分段 ping 或 telnet 测试来验证。但注意不要用 ICMP ping 的结果来判断 TCP 端口是否可达因为很多网络设备对 ICMP 和 TCP 的 ACL 策略是独立配置的。这里的教训是ping 通不代表端口通两者要分开验证。4.2 真相是防火墙只放行了 UDP 53配置验证与修改建议派人到办公室之间的路由器上看配置后问题浮现了路由器的访问控制列表只允许 UDP 53 端口进入中心办公室网络TCP 53 被 deny 了。这解释了 SYN 包为什么到不了总部 DNS 服务器。这种配置的错误在于配置者只考虑了 DNS 查询走 UDP 的常规路径忽略了 DNS 区域传送依赖 TCP。常见的企业防火墙策略中很多人只放行udp/53导致区域传送静默失败。修改也很简单在 ACL 中增加一条access-list 120 permit tcp 172.16.16.0 0.0.0.255 host 172.16.16.250 eq domain在 Cisco 设备上eq domain等价于eq 53作用就是放行分支网段到总部 DNS 服务器的 TCP 53 流量。修改后记得敲clear access-list counters清掉旧的命中计数方便后续观察新策略是否生效。对于其他厂商设备核心逻辑是一样的在入方向允许 TCP 目的端口 53 的流量进入。5. Wireshark 排查 DNS 故障的避坑指南五个常见误判5.1 误判一看到 SERVFAIL 就认为是 DNS 服务器宕机现象DNS 响应返回SERVFAIL检查 DNS 服务器进程发现正常运行没有任何异常日志。原因SERVFAIL是 DNS 服务器向上游请求失败时返回的兜底错误服务器本身状态健康不代表它的上游链路健康。解决在 DNS 服务器上做一次dig 127.0.0.1和dig 上游服务器的对比测试确认是哪个环节丢的响应。5.2 误判二只抓终端侧包不抓服务器侧包现象终端侧能看到请求发出和响应返回但无法定位是哪个环节出了错。原因单点抓包只能证明这里看到了什么无法证明其他地方发生了什么。解决至少同时在客户端、本地 DNS 服务器、上游 DNS 服务器三个点抓包用时间戳对齐来做链路还原。实际操作中先改端口镜像把嗅探器移到 DNS 服务器侧确认请求是否到达了服务器。5.3 误判三认为 DNS 一定走 UDP忽略 TCP 场景现象看到 TCP 53 端口的 SYN 包以为是攻击流量直接忽略导致区域传送失败的问题被掩盖。原因DNS 确实主要走 UDP但区域传送和超大响应场景必须走 TCP这是协议设计的一部分。解决碰到 TCP 53 的流量先判断前置是否有 TC 标志的 UDP 响应或者是否来自已知的从属 DNS 服务器再决定要不要进一步调查。5.4 误判四只修改防火墙规则不验证是否真的生效现象ACL 改了问题没有恢复重新抓包发现 SYN 仍然没有到达对端。原因ACL 修改可能没保存或者配置在了错误的接口方位。解决改完配置后立刻在两侧同时抓包确认新的 SYN 包已经穿过链路。可以从路由器 ping DNS 服务器然后看计数器是否增长。在真实场景中区分策略没改对和策略之外的路径还有问题非常重要。5.5 误判五用 ping 通来替代 TCP 端口连通性验证现象ping DNS 服务器通了就认为链路正常忽略了 TCP 53 被拦截的问题。原因ICMP 和 TCP 是不同的协议ACL 针对协议类型分别配置时完全可能 ICMP 放行而 TCP 拦掉。解决用nc -vz ip 53或者telnet ip 53来做 TCP 端口连通性测试测试结果才是 TCP 层真正的通行状态。6. 验证修复效果的抓包方法从 pcap 对比到完整的链路复测修复路由器 ACL 之后问题是否真的解决不能只靠用户说能打开了来判断必须回到抓包层面做正向验证。我是这样做的把嗅探器保持在分支 DNS 服务器侧重新开启捕获观察是否有正常的 TCP 三次握手出现在 53 端口上。正常的区域传送流量序列是分支 DNS 发出 SYN总部 DNS 回 SYN-ACK分支 DNS 再回 ACK三次握手完成后开始传输数据。这个序列在 Wireshark 里看起来非常清晰是四个阶段连接的典型情形。可以用 Wireshark 的流量统计功能查看 TCP 会话列表过滤tcp.port53看看会话状态是不是已经从SYN_SENT变成了ESTABLISHED。再往前推一步应该回到工作站侧重复最初的两包捕获确认 A 记录查询能够拿到正确的响应。如果响应的Answers字段中出现了目标 IP172.16.16.200同时Flags显示No error就说明整条链路的解析路径已经打通。客户端拿到 IP 后还会发起到 172.16.16.200 的 TCP 握手这也是一个附加验证。最后还要做一件事把这次排查的过滤表达式和关键时间点记录下来。比如用dns.flags.rcode 2定位故障窗口用tcp.dstport 53 tcp.flags.syn 1定位区域传送起点。这些表达式在下次遇到相似问题时可以直接套用。从那以后我每接手一个 DNS 故障案例都会强制自己走一遍客户端抓包 → DNS 服务器抓包 → 链路中间点抓包的三段式验证流程从不在只有一端数据的情况下提前下结论。这个习惯帮我躲过了好几次因为只看到部分流量而产生的判断失误希望这次案例拆解也能帮你在之后的抓包排查中少走一些弯路。本文还有配套的精品资源点击获取