封包分析实践指南第三版-全-
封包分析实践指南第三版(全)
原文:
zh.annas-archive.org/md5/f476d34b12001ecad9265c89e223fc59译者:飞龙
前言

这本实用的数据包分析的第三版是在 2015 年底到 2017 年初之间的一年半时间里编写和编辑的,大约是在第二版发布后 6 年,原版发布后的 10 年。这本书包含了大量新的内容,完全新的捕获文件和场景,并且增加了一个全新的章节,介绍了如何通过命令行使用 TShark 和 tcpdump 进行数据包分析。如果你喜欢前两版,那么你一定会喜欢这一版。它保持了相同的风格,解释简单易懂。如果你因为前两版没有包括最新的网络或 Wireshark 更新信息而犹豫过,那你一定会想读这一版,因为它扩展了新网络协议的内容,并且提供了关于 Wireshark 2.x的更新信息。
为什么选择这本书?
你可能会想,为什么你应该购买这本书,而不是其他任何一本关于数据包分析的书?答案就在于书名:实用的数据包分析。说实话——没有什么比实际经验更有价值,而在书本中,最接近这种经验的就是通过实际示例和真实场景来呈现。
本书的前半部分将为你提供理解数据包分析和 Wireshark 所需的知识。后半部分则完全专注于你在日常网络管理中可能遇到的实际案例。
无论你是网络技术员、网络管理员、首席信息官、桌面技术员,还是网络安全分析员,你都会从理解并使用本书中描述的数据包分析技术中获益良多。
概念与方法
我通常是个非常随和的人,因此当我讲解一个概念时,我尽量以一种非常轻松的方式进行。这一点在本书的语言中也有所体现。技术术语很容易让人迷失,但我尽力保持内容尽可能简单。我已经清晰地定义了所有术语和概念,没有任何多余的修饰。毕竟,我来自肯塔基州,所以我尽量避免使用复杂的词汇。(不过,你得原谅我在文本中使用的一些乡土语言。)
前几章对理解本书的其余部分至关重要,因此请务必先掌握这些章节中的概念。后半部分完全是实践内容。你可能不会在工作中遇到完全相同的场景,但你将能够将它们教授的概念应用到你实际遇到的情况中。
以下是本书内容的快速概述:
第一章:数据包分析与网络基础
什么是数据包分析?它是如何工作的?你如何进行数据包分析?本章介绍了网络通信和数据包分析的基础知识。
第二章:接入网络线
本章介绍了将数据包嗅探器放置在网络上的不同技术。
第三章:Wireshark 简介
在这一部分,我们将了解 Wireshark 的基础知识——它来自哪里、如何使用、它能做什么、为什么它很棒,以及所有相关的内容。本版本新增了关于使用配置文件定制 Wireshark 的讨论。
第四章:处理捕获的数据包
当你启动并运行 Wireshark 后,你需要了解如何与捕获的数据包进行交互。在这一部分,你将学习一些基础知识,包括关于跟踪数据包流和名称解析的更详细的新内容。
第五章:Wireshark 的高级功能
一旦你学会了如何入门,就该加速前进了。本章深入探讨 Wireshark 的高级功能,带你深入幕后,展示一些不太显眼的操作内容。这里包括关于跟踪数据包流和名称解析的全新、更详细的章节。
第六章:命令行上的数据包分析
Wireshark 很棒,但有时你需要离开图形界面的舒适区,通过命令行与数据包进行交互。本章将向你展示如何使用 TShark 和 tcpdump,这两款最适合此任务的命令行数据包分析工具。
第七章:网络层协议
本章通过检查 ARP、IPv4、IPv6 和 ICMP,展示了常见网络层通信在数据包层级的表现。要在实际场景中排除这些协议的问题,首先需要理解它们的工作原理。
第八章:传输层协议
本章讨论了两种最常见的传输协议,TCP 和 UDP。你查看的大多数数据包都会使用这两种协议之一,因此了解它们在数据包层级的表现及其差异非常重要。
第九章:常见上层协议
本章继续讨论协议,展示四个最常见的上层网络通信协议——HTTP、DNS、DHCP 和 SMTP——在数据包层级的表现。
第十章:基础的真实世界场景
本章包含了一些常见流量的分析和第一批真实世界的场景。每个场景都以易于跟随的格式呈现,给出问题、分析和解决方案。这些基础场景只涉及少数几台计算机,并进行有限的分析——刚好足够让你入门。
第十一章:应对缓慢的网络
网络技术人员最常听到的问题通常涉及网络性能缓慢。本章专门解决这类问题。
第十二章:安全性数据包分析
网络安全是信息技术领域最热门的话题之一。第十二章向你展示了与解决安全相关问题的数据包分析技术的应用场景。
第十三章:无线数据包分析
本章是无线数据包分析的入门。它讨论了无线分析与有线分析之间的区别,并包括了一些无线网络流量的示例。
附录 A:进一步阅读
本书的第一个附录建议了一些你在继续使用你所学的数据包分析技术时可能会发现有用的参考工具和网站。
附录 B:数据包导航
如果你想深入理解如何解析单个数据包,本书的第二个附录提供了有关数据包信息如何以二进制格式存储,以及如何将二进制转换为十六进制表示法的概述。接下来,它会向你展示如何使用数据包图示解析以十六进制表示的数据包。如果你打算花大量时间分析自定义协议或使用命令行分析工具,这一点将非常有用。
如何使用本书
我希望这本书有两种使用方式:
• 作为一本教育性读物。 你将逐章阅读,特别注意后面章节中的实际场景,以便理解数据包分析。
• 作为参考资料。 Wireshark 中有一些功能你可能不会经常使用,因此你可能会忘记它们的工作原理。《实用数据包分析》是一本很适合放在书架上的书,当你需要快速回顾如何使用某个特定功能时,它会派上用场。在做数据包分析时,你可能会想参考我提供的独特图表、图示和方法论。
关于示例捕获文件
本书中使用的所有捕获文件都可以从本书的 No Starch Press 页面获取,* www.nostarch.com/packetanalysis3/*。为了最大化本书的潜力,下载这些文件并在跟随示例时使用它们。
乡村技术基金
我无法写出一篇介绍,而不提到《实用数据包分析》带来的最大亮点。在本书第一版发布后不久,我创办了一个 501(c)(3)非营利组织——乡村技术基金(RTF)。
即便是那些成绩优异的农村学生,往往也比城市或郊区的同龄人更少接触到科技。RTF 成立于 2008 年,是我最大梦想之一的结晶。它旨在缩小农村社区与城市和郊区之间的数字鸿沟。RTF 通过定向奖学金项目、社区参与、向教室捐赠教育技术资源以及在农村和高贫困地区广泛推广和倡导科技来实现这一目标。
2016 年,RTF 成功将科技教育资源交到美国农村及高贫困地区超过 10,000 名学生手中。我很高兴地宣布,本书所有的作者所得将直接捐赠给 RTF,以支持这些目标。如果您想了解更多关于农村科技基金的信息或如何参与捐赠,请访问我们的网站 www.ruraltechfund.org/,或在 Twitter 上关注我们 @RuralTechFund。
联系我
我总是很高兴收到读者对我的写作的反馈。如果您有任何问题、评论、建议或婚姻提议,欢迎直接通过 chris@chrissanders.org 联系我。我也会定期写博客,您可以访问 www.chrissanders.org/,同时也可以在 Twitter 上关注我 @chrissanders88。
第一章:数据包分析与网络基础

每天,计算机网络中可能出现无数种问题——从简单的间谍软件感染到复杂的路由器配置错误——而且不可能立即解决每个问题。我们能做的最好的准备就是拥有应对这些问题所需的知识和工具。
要真正理解网络问题,我们需要从数据包级别入手。所有的网络问题都源自这个层次,在这里,即便是最美观的应用程序也能揭示它们糟糕的实现,而看似值得信任的协议也可能证明是恶意的。在这里,什么都不会被隐藏。没有什么能够通过误导性的菜单结构、引人注目的图形或不可信的员工而被掩盖——没有真正的秘密(只有加密的秘密)。我们在数据包级别上能做的越多,我们就能越多地控制我们的网络并解决问题。这就是数据包分析的世界。
本书将深入探讨这个领域。通过真实场景,你将学习如何解决网络通信缓慢、识别应用程序瓶颈,甚至追踪黑客。读完本书后,你应该能够实施数据包分析技术,帮助你解决自己网络中最棘手的问题。
本章将从基础知识开始,重点介绍网络通信。本部分内容将帮助你获得分析不同场景所需的工具。
数据包分析和数据包嗅探器
数据包分析,通常称为数据包嗅探或协议分析,描述了捕获和解读网络中实时数据流动的过程,目的是更好地理解网络上发生的事情。数据包分析通常由数据包嗅探器执行,这是一种用于捕获通过网络传输的原始数据的工具。
数据包分析可以帮助完成以下任务:
• 理解网络特性
• 了解谁在网络上
• 确定谁或什么在使用可用带宽
• 识别网络使用的高峰时间
• 识别恶意活动
• 寻找不安全且臃肿的应用程序
有多种类型的数据包嗅探程序,包括免费和商业版的。每个程序都有不同的目标。一些流行的数据包分析程序包括 tcpdump、OmniPeek 和 Wireshark(本书主要使用 Wireshark)。OmniPeek 和 Wireshark 具有图形用户界面(GUI),而 tcpdump 是一个命令行程序。
评估数据包嗅探器
在选择数据包嗅探器时,你需要考虑多个因素,包括以下几点:
支持的协议 所有数据包嗅探器都能够解读各种协议。大多数能够解读常见的网络协议(如 IPv4 和 ICMP)、传输协议(如 TCP 和 UDP),甚至应用程序协议(如 DNS 和 HTTP)。然而,它们可能不支持非传统的、更复杂的或较新的协议(如 IPv6、SMBv2 和 SIP)。在选择嗅探器时,确保它支持你将要使用的协议。
用户友好性 考虑数据包嗅探器的布局、安装的简便性以及整体工作流程。你选择的程序应该适合你的专业水平。如果你在数据包分析方面经验很少,你可能想避免使用像 tcpdump 这样的高级命令行数据包嗅探器。另一方面,如果你是数据包分析的老手,你可能会发现一个高级程序更为有用。随着经验的积累,你甚至可能会发现结合多个数据包嗅探程序以应对特定场景是非常有用的。
成本 数据包嗅探器的一个好处是有许多免费的嗅探器,它们的性能可以媲美任何商业产品。商业产品与其免费的替代品之间最显著的区别在于它们的报告引擎。商业产品通常包括某种形式的精美报告生成模块,而免费应用程序通常没有这种功能,或者仅提供非常有限的报告功能。
程序支持 即使你已经掌握了嗅探程序的基础知识,你可能仍然需要支持来解决随着新问题的出现而产生的挑战。在评估可用支持时,寻找开发者文档、公共论坛和邮件列表。虽然像 Wireshark 这样的免费数据包嗅探程序可能缺乏正式的商业支持,但用户和贡献者社区通常会提供活跃的讨论板、维基和博客,帮助你更好地使用数据包嗅探器。
源代码访问 一些数据包嗅探器是开源软件。这意味着你可以查看程序的源代码,在某些情况下,甚至可以提出建议并对源代码进行更改。如果你有非常具体或高级的嗅探应用需求,这可能是一个非常吸引人的特点。大多数商业应用程序不提供源代码访问。
操作系统支持 不幸的是,并不是所有数据包嗅探器都支持每一个操作系统。请选择一个可以在所有你需要支持的操作系统上运行的工具。如果你是顾问,你可能需要在多种操作系统上捕获和分析数据包,因此你需要一个可以在大多数操作系统上运行的工具。另外,请记住,你有时可能会在一台机器上捕获数据包,并在另一台机器上进行查看。操作系统之间的差异可能迫使你在每个设备上使用不同的应用程序。
数据包嗅探器的工作原理
数据包嗅探过程涉及软件和硬件的协同工作。这个过程可以分为三个步骤:
-
收集: 首先,数据包嗅探器从网络中收集原始的二进制数据。通常通过将选定的网络接口切换到混杂模式来实现。在此模式下,网络卡可以监听网络段上的所有流量,而不仅仅是发送给它的流量。
-
转换: 接下来,将捕获的二进制数据转换为可读形式。这是大多数高级命令行数据包嗅探器能够做到的极限。在此阶段,网络数据只能在非常基础的层面进行解读,剩下的大部分分析则交由最终用户完成。
-
分析: 最后,数据包嗅探器对捕获并转换后的数据进行分析。嗅探器根据提取的信息验证捕获的网络数据的协议,并开始分析该协议的特定特性。
计算机如何通信
要完全理解数据包分析,你必须了解计算机是如何相互通信的。在本节中,我们将研究网络协议的基础知识、开放系统互联(OSI)模型、网络数据帧以及支撑这一切的硬件。
协议
现代网络由运行在多种不同平台上的各种系统组成。为了在系统之间进行通信,我们使用一套称为协议的通用语言。常见的协议包括传输控制协议(TCP)、互联网协议(IP)、地址解析协议(ARP)和动态主机配置协议(DHCP)。多个协同工作的协议组合被称为协议栈。
可以把协议想象成类似于控制人类语言的规则。每种语言都有一些规则,比如动词变位、如何打招呼,甚至如何恰当地表达感谢。协议的工作方式也类似,允许我们定义数据包应该如何路由,如何初始化连接,以及如何确认接收数据。
协议可以是非常简单的,也可以是高度复杂的,具体取决于其功能。尽管各种协议可能存在显著差异,但许多协议都涉及以下问题:
连接初始化 是客户端还是服务器发起了连接?在通信之前必须交换哪些信息?
连接特征的协商 协议的通信是否经过加密?加密密钥是如何在通信主机之间传输的?
数据格式化 数据包内的数据是如何组织的?接收设备处理数据的顺序是怎样的?
错误检测与修正 如果数据包在传输过程中花费太长时间才到达目的地,会发生什么情况?如果客户端在短时间内无法与服务器建立通信,如何恢复?
连接终止 一个主机如何向另一个主机表示通信已经结束?为了优雅地终止通信,必须传输哪些最终信息?
七层 OSI 模型
协议根据其功能根据行业标准的 OSI 参考模型进行分离。这个七层的分层模型有助于理解网络通信。在图 1-1 中,OSI 模型的层级位于右侧,而每一层的数据术语位于左侧。顶部的应用层代表用于访问网络资源的程序。最底层是物理层,网络数据通过它传输。每一层的协议共同作用,确保数据在上下层协议之间得到正确处理。
注意
OSI 模型最初由国际标准化组织(ISO)于 1983 年发布,作为名为 ISO 7498 的文档。OSI 模型只是一个行业推荐的标准。协议开发人员并不要求严格遵循它。事实上,OSI 模型并不是唯一的网络模型;例如,有些人更倾向于使用国防部(DoD)模型,也称为 TCP/IP 模型。

图 1-1:OSI 模型七层的分层视图
每个 OSI 模型层都有特定的功能,如下所示:
应用层(第 7 层) OSI 模型的最顶层为用户提供访问网络资源的方式。这是终端用户通常看到的唯一一层,因为它提供了所有网络活动的基础接口。
表示层(第 6 层) 该层将接收到的数据转化为应用层可以读取的格式。这里的数据编码和解码依赖于发送或接收数据的应用层协议。表示层还处理几种形式的加密和解密,用于保护数据安全。
会话层(第 5 层) 该层管理两台计算机之间的对话,或会话。它在所有通信设备之间建立、管理和终止连接。会话层还负责确定连接是双工(双向)还是半双工(单向),并且负责优雅地关闭主机之间的连接,而不是突然中断连接。
传输层(第 4 层) 传输层的主要目的是为下层提供可靠的数据传输服务。通过流量控制、分段/重组和错误控制,传输层确保数据从源点到目的点无误传输。由于确保可靠的数据传输可能非常繁琐,OSI 模型专门为此设立了一个层级。传输层使用面向连接和无连接的协议。某些防火墙和代理服务器在这一层工作。
网络层(第 3 层) 这一层是 OSI 模型中最复杂的层之一,负责在物理网络之间路由数据。它负责网络主机的逻辑寻址(例如,通过 IP 地址)。它还处理将数据流分割成较小的片段,并在某些情况下进行错误检测。路由器在这一层操作。
数据链路层(第 2 层) 这一层提供了一种在物理网络中传输数据的方法。其主要目的是提供一种可以用来识别物理设备的寻址方案(例如,MAC 地址)。桥接器和交换机是操作在数据链路层的物理设备。
物理层(第 1 层) OSI 模型最底层是网络数据传输的物理介质。此层定义了所有硬件的物理和电气特性,包括电压、集线器、网络适配器、中继器和电缆规格。物理层建立和终止连接,提供共享通信资源的方式,并将信号从数字转换为模拟,反之亦然。
注意
记忆 OSI 模型各层的一种常用助记符是 Please Do Not Throw Sausage Pizza Away. 每个单词的首字母代表 OSI 模型的每一层,从第一层开始。
表 1-1 列出了 OSI 模型各层中常用的一些协议。
表 1-1: OSI 模型各层中常用的协议
| 层级 | 协议 |
|---|---|
| 应用层 | HTTP, SMTP, FTP, Telnet |
| 表现层 | ASCII, MPEG, JPEG, MIDI |
| 会话层 | NetBIOS, SAP, SDP, NWLink |
| 传输层 | TCP, UDP, SPX |
| 网络层 | IP, IPX |
| 数据链路层 | 以太网, 令牌环, FDDI, AppleTalk |
| 物理层 | 有线, 无线 |
虽然 OSI 模型仅仅是一个推荐标准,但你应该将它记住,因为它为思考和描述网络问题提供了有用的词汇。随着我们深入本书,你会发现路由器问题很快就成为“第 3 层问题”,而软件问题则被迅速识别为“第 7 层问题”。
注意
有一次,一位同事告诉我,某用户抱怨无法访问网络资源。问题的根本原因是用户输入了错误的密码。我的同事将此称为 第 8 层问题。 第 8 层是非官方的用户层。这个术语在那些生活在数据包层次的人中非常常见。
数据流通过 OSI 模型
网络上的初始数据传输始于发送系统的应用层。数据逐层通过 OSI 模型的七个层级,直到到达物理层,此时发送系统的物理层将数据发送到接收系统。接收系统在其物理层接收数据,然后数据沿着接收系统的各层向上传递,最终到达最上层的应用层。
OSI 模型中的每一层只能与其上下直接相邻的层进行通信。例如,第 2 层只能与第 1 层和第 3 层进行数据交换。
在 OSI 的任何给定层级中,各种协议提供的服务都不是冗余的。例如,如果某一层的协议提供了特定服务,那么其他层级的协议将不会提供相同的服务。不同层级的协议可能具有类似的目标,但它们的实现方式会有所不同。
发送和接收设备上对应层次的协议是互补的。例如,如果发送设备第 7 层的协议负责格式化传输的数据,那么接收设备第 7 层的对应协议则应负责读取这些格式化的数据。
图 1-2 是 OSI 模型与两个通信设备相关的图示。你可以看到数据从一个设备的顶部向下传输,随后当数据到达第二个设备时,传输方向会反转。

图 1-2:发送和接收系统中相同层次工作的协议
数据封装
OSI 模型中不同层次的协议通过数据封装相互传递数据。堆栈中的每一层都负责在传输的数据上添加一个头部或尾部——这些附加的位置信息允许各层之间进行通信。例如,当传输层从会话层接收数据时,传输层会在传输的数据上添加自己的头部信息,然后将其传递给网络层。
封装过程会创建一个协议数据单元(PDU),它包括被发送的数据和所有附加的头部或尾部信息。随着数据沿着 OSI 模型向下流动,各种协议会添加头部和尾部信息,PDU 会发生变化并不断增长。当 PDU 到达物理层时,它已处于最终形式,此时它将被发送到目标设备。接收设备在数据沿着 OSI 层次反向流动时,会去除 PDU 中的协议头部和尾部。最终,当 PDU 到达 OSI 模型的顶层时,只剩下原始的应用层数据。
注意
OSI 模型使用特定的术语来描述每个层次中的封装数据。物理层包含比特,数据链路层包含帧,网络层包含数据包,传输层包含段。前三层仅使用数据一词。这种命名法在实践中并不常用,因此我们通常仅使用数据包一词来指代包括来自一个或多个 OSI 模型层的头部和尾部信息的完整或部分 PDU。
为了说明数据封装是如何工作的,我们将通过一个简化的实际示例来展示数据包的构建、传输和接收过程,这与 OSI 模型有关。请记住,作为分析师,我们通常不会讨论会话层或表现层,因此在这个示例中(以及本书的其余部分)这两个层将不涉及。
在此场景中,我们正在尝试浏览* www.google.com/ *。首先,我们必须生成一个请求数据包,该数据包从我们的源客户端计算机传输到目标服务器计算机。此场景假设 TCP/IP 通信会话已经建立。图 1-3 展示了此示例中的数据封装过程。
我们从客户端计算机的应用层开始。我们正在浏览一个网站,因此所使用的应用层协议是 HTTP;HTTP 协议将发出命令,从* google.com 下载文件 index.html*。
注意
在实际操作中,浏览器首先会请求网站的文档根目录,这通常用斜杠(/)表示。当 web 服务器收到此请求时,它会将浏览器重定向到配置文件中指定的文件,通常是 index.html 或 index.php。 我们将在第九章讨论 HTTP 时进一步介绍这一过程。
一旦我们的应用层协议发送了命令,我们关注的就是如何将数据包送达目标。数据包中的数据会沿着 OSI 协议栈向下传递到传输层。HTTP 是一个应用层协议,它使用(或基于)TCP,因此 TCP 作为传输层协议,确保数据包的可靠传输。生成一个 TCP 头,并将其添加到 PDU 中,如图 1-3 所示。此 TCP 头包含序列号及其他数据,这些信息会附加到数据包中,确保数据包的正确传送。

图 1-3:客户端和服务器之间数据封装的图形表示
注意
我们常说一个协议“依赖于”或“建立在”另一个协议之上,因为 OSI 模型的自上而下设计。例如,像 HTTP 这样的应用协议提供特定服务,并依赖 TCP 确保其服务的可靠交付。这两种服务都依赖网络层的 IP 协议来寻址和传递数据。因此,HTTP 建立在 TCP 之上,而 TCP 则建立在 IP 之上。
完成其工作后,TCP 将数据包交给 IP,后者是负责数据包逻辑寻址的第三层协议。IP 创建一个包含逻辑寻址信息的头部,将其添加到 PDU 中,并将数据包传递到数据链路层的以太网。物理以太网地址存储在以太网头部中。数据包现在已经完全组装好,并传递到物理层,在那里它以零和一的形式穿越网络。
完整的数据包穿过网络布线系统,最终到达 Google Web 服务器。Web 服务器首先从底层向上读取数据包,这意味着它首先读取数据链路层,其中包含网络卡用来确定数据包是否指向特定服务器的物理以太网地址信息。一旦这些信息处理完毕,第二层信息会被去除,接着处理第三层信息。
第 3 层的 IP 寻址信息被读取,以确保数据包地址正确并且未被分段。此数据也会被去除,以便处理下一个层次的信息。
第 4 层 TCP 信息现在被读取,以确保数据包按顺序到达。然后,第 4 层的头部信息被去除,只留下应用层数据,这些数据可以传递给托管网站的 Web 服务器应用程序。为了响应来自客户端的数据包,服务器应该传输一个 TCP 确认数据包,以便客户端知道它的请求已被接收,随后是index.html文件。
所有的数据包都是按照这个示例中的描述构建和处理的,无论使用什么协议。但是,同时请记住,并非每个网络上的数据包都是由应用层协议生成的,因此你会看到只包含第二层、第三层或第四层协议信息的数据包。
网络硬件
现在是时候看看网络硬件了,这是完成“脏活”的地方。我们将重点介绍一些常见的网络硬件:集线器、交换机和路由器。
集线器
集线器通常是一个带有多个 RJ-45 端口的盒子,像图 1-4 所示的 NETGEAR 集线器。集线器的大小从非常小的 4 端口设备到设计用于在企业环境中机架安装的更大 48 端口设备不等。

图 1-4:典型的 4 端口以太网集线器
由于集线器可能产生大量不必要的网络流量,并且只能在半双工模式下工作(它们不能同时发送和接收数据),因此在大多数现代或高密度网络中通常看不到它们的身影;而是使用交换机(将在下一节讨论)。然而,你应该了解集线器的工作原理,因为在使用第二章中讨论的“集线器外发”技术时,它们对于数据包分析将非常重要。
集线器不过是一个重复设备,它在 OSI 模型的物理层上运行。它接收从一个端口发送的数据包,并将其传输(重复)到设备上的所有其他端口,接收设备负责接受或拒绝每个数据包。例如,如果一个连接到 4 端口集线器端口 1 的计算机需要向端口 2 的计算机发送数据,集线器会将这些数据包发送到端口 2、3 和 4。连接到端口 3 和 4 的客户端会检查数据包以太网头部中的目标媒体访问控制(MAC)地址字段,发现数据包不是发给它们的,因此它们会丢弃(丢弃)该数据包。图 1-5 展示了一个示例,其中计算机 A 向计算机 B 传输数据。当计算机 A 发送此数据时,所有连接到集线器的计算机都会接收到数据。然而,只有计算机 B 会接受该数据;其他计算机会丢弃该数据。

图 1-5:计算机 A 通过集线器向计算机 B 传输数据时的流量情况
举个例子,假设你给公司每一位员工发送了主题为“全体营销人员注意”的电子邮件,而不是只发送给营销部门的员工。营销部门的员工看到邮件是发给他们的,就打开了邮件;其他员工看到邮件不是发给他们的,就把邮件丢弃。你可以看出,这种沟通方式会导致大量不必要的流量和时间浪费,而这正是集线器的工作方式。
在生产环境和高密度网络中,最好的集线器替代品是交换机,它们是全双工设备,可以同步发送和接收数据。
交换机
与集线器类似,交换机也被设计为重复数据包。然而,与集线器不同的是,交换机并不是将数据广播到每个端口,而是只将数据发送到目标计算机。交换机看起来与集线器非常相似,如图 1-6 所示。

图 1-6:一款 48 端口机架式以太网交换机
市面上一些较大的交换机,例如思科品牌的交换机,通常通过专用的厂商特定软件或网页界面进行管理。这些交换机通常被称为托管交换机。托管交换机提供了一些在网络管理中非常有用的功能,包括启用或禁用特定端口、查看端口统计信息、进行配置更改以及远程重启等功能。
交换机还提供了处理传输数据包的高级功能。为了能够与特定设备直接通信,交换机必须能够根据设备的 MAC 地址唯一识别设备,这意味着它们必须在 OSI 模型的数据链路层上操作。
交换机将每个连接设备的二层地址存储在一个CAM 表中,这个表充当了一个交通警察。当一个数据包被传输时,交换机会读取数据包中的二层头信息,并使用 CAM 表作为参考,决定将数据包发送到哪个端口。交换机只将数据包发送到特定的端口,从而大大减少了网络流量。
图 1-7 展示了通过交换机的流量流动。在这个图中,计算机 A 仅将数据发送给目标接收方:计算机 B。多个对话可以同时在网络上发生,但信息是直接在交换机与目标接收方之间传输,而不是在交换机与所有连接的计算机之间传输。

图 1-7:计算机 A 通过交换机将数据传输到计算机 B 时的流量流动
路由器
路由器是一种功能远超交换机或集线器的高级网络设备。路由器有许多不同的形状和形式,但大多数设备的前面有几个 LED 指示灯,背面有一些网络端口,具体取决于网络的大小。图 1-8 展示了一个小型路由器的示例。

图 1-8:适用于小型到中型网络的低端 Enterasys 路由器
路由器在 OSI 模型的第三层操作,负责在两个或多个网络之间转发数据包。路由器用于指导网络间流量流动的过程被称为路由。几种不同类型的路由协议决定了如何将不同类型的数据包路由到其他网络。路由器通常使用第三层地址(例如 IP 地址)来唯一标识网络上的设备。
一个很好的方法来说明路由的概念是用有多条街道的社区作类比。把每栋房子及其地址看作是计算机。然后把每条街道看作是一个网络段。图 1-9 展示了这个对比。从你的房子出发,你可以通过从你家门口直走到邻居家门口的方式,轻松拜访住在同一街道上的邻居。同样,交换机允许网络段内所有计算机之间进行通信。
然而,与住在另一条街道的邻居沟通就像与不在同一网段的计算机通信。参见图 1-9,假设你坐在 502 Vine Street,需要到达 206 Dogwood Lane。为了做到这一点,你必须先转到 Oak Street,然后转到 Dogwood Lane。可以将这看作是跨越网络段。如果 192.168.0.3 的设备需要与 192.168.0.54 的设备通信,它必须跨越一个路由器才能进入 10.100.1.x 网络,然后再跨越目标网络段的路由器,才能到达目标网络段。
网络上路由器的数量和大小通常取决于网络的规模和功能。个人和家庭办公室网络可能只有一个小型路由器,位于网络的边缘。而大型企业网络可能在各个部门之间有多个路由器,这些路由器都连接到一个大型中央路由器或层 3 交换机(这是一种高级交换机,具有内置的路由器功能)。

图 1-9:路由网络与街道的比较
随着你查看越来越多的网络图,你将逐渐理解数据如何通过这些不同的点流动。图 1-10 展示了一个非常常见的路由网络的布局。在这个例子中,两个独立的网络通过一个路由器连接。如果网络 A 上的计算机希望与网络 B 上的计算机通信,那么传输的数据必须经过路由器。

图 1-10:计算机 A 在一个网络上传输数据到另一个网络上的计算机 X 时,流量的流动
流量分类
网络流量可以分为三种类型:广播、组播和单播。每种类型都有独特的特征,决定了该类数据包如何被网络硬件处理。
广播流量
一个广播数据包是发送到网络段上所有端口的数据包,无论给定端口是集线器还是交换机。
广播流量有层 2 和层 3 两种形式。在层 2,MAC 地址 ff:ff:ff:ff:ff:ff 是保留的广播地址,发送到这个地址的任何流量都会广播到整个网络段。层 3 也有一个特定的广播地址,但它根据使用的网络地址范围而有所不同。
一个 IP 网络范围内最高的 IP 地址是保留用作广播地址的。例如,如果你的计算机地址是 192.168.0.20,子网掩码是 255.255.255.0,那么 192.168.0.255 就是广播地址(有关 IP 地址的更多信息,请参见第七章)。
广播包可以传播的范围称为广播域,这是一个网络段,任何计算机都可以直接向另一台计算机发送数据包,而无需通过路由器。在拥有多个集线器或交换机并通过不同介质连接的较大网络中,从一个交换机发送的广播包会传送到网络中所有其他交换机的所有端口,因为广播包会从一个交换机重复传送到另一个交换机。图 1-11 展示了一个小型网络中两个广播域的示例。由于每个广播域会扩展到路由器,因此广播包仅在这个指定的广播域内循环。

图 1-11:广播域扩展到当前路由段后面的所有内容。
我们之前的邻里类比也很好地帮助理解了广播域是如何工作的。你可以把广播域想象成一个邻里街道,街道上所有的邻居都坐在自家的门廊上。如果你站在门廊上大喊,街道上的人都会听到你。然而,如果你想和不同街道上的人交谈,你需要找到一种方式直接与那个人沟通,而不是从门廊上大喊(广播)。
多播流量
多播是一种将数据包从单一源同时传输到多个目的地的方式。多播的目标是尽可能使用最少的带宽。优化这种流量的方法在于,数据流沿路径复制的次数较少,直到到达目的地。多播流量的具体处理方式高度依赖于各个协议的实现。
实现多播流量的主要方法是通过一种寻址方案,将数据包接收者加入到一个多播组中。这就是 IP 多播的工作方式。这种寻址方案确保数据包不会被传输到不属于目标的计算机。实际上,IP 专门为多播保留了一个完整的地址范围。如果你看到一个 IP 地址在 224.0.0.0 到 239.255.255.255 的范围内,那么它很可能是在处理多播流量,因为这些范围是为此目的保留的。
单播流量
单播数据包是从一台计算机直接传输到另一台计算机。单播的具体功能取决于使用它的协议。例如,假设有一个设备想与一台网页服务器进行通信。这是一个一对一的连接,因此,通信过程将从客户端设备向网页服务器发送数据包开始。
总结思考
本章介绍了你作为数据包分析基础所需的网络基础知识。在开始排查网络问题之前,你必须理解这一层次的网络通信发生了什么。在第二章中,我们将探讨多种捕获你需要分析的数据包的技术。
第二章:接入网络线路

对于有效的数据包分析来说,关键决策之一是将数据包嗅探器物理放置在哪个位置,以便适当地捕获数据。数据包分析员通常称将数据包嗅探器放置到网络中为嗅探线路、接入网络或接入网络线路。
不幸的是,嗅探数据包并不像将笔记本电脑插入网络端口并捕获流量那么简单。实际上,有时将数据包嗅探器放置到网络上,比实际分析数据包还要困难。嗅探器的放置具有挑战性,因为设备可以通过多种不同的网络硬件进行连接。图 2-1 展示了一个典型情况。由于现代网络中的设备(交换机和路由器)对流量的处理方式不同,因此在分析网络时,必须考虑到网络的物理布局。
本章的目标是帮助你理解在不同网络拓扑中放置数据包嗅探器的方式。但首先,让我们来看看我们是如何看到所有穿越我们接入的网络线路的数据包的。

图 2-1:当网络连接较多时,放置嗅探器在网络上可能会具有挑战性,获取所需的数据也可能变得棘手。
肆意生活
在你能够嗅探网络上的数据包之前,你需要一张支持混杂模式驱动程序的网络接口卡(NIC)。混杂模式允许 NIC 查看所有穿越线路的数据包。
正如你在第一章中学到的那样,在网络广播流量中,设备通常会接收到并非专门发送给它们的数据包。例如,地址解析协议(ARP)是任何网络中至关重要的协议,我们将在第七章中深入探讨,它用于确定哪个 MAC 地址与特定的 IP 地址相对应。为了找到匹配的 MAC 地址,设备会向其广播域中的所有设备发送 ARP 广播数据包,希望正确的设备能够响应。
广播域(任何计算机可以直接向另一台计算机发送数据包而不通过路由器的网络段)可以由多台设备组成,但只有广播域中正确的接收设备应该对所传输的 ARP 广播数据包感兴趣。如果网络上的每一台设备都处理 ARP 广播数据包,那将是极其低效的。相反,如果数据包不是面向该设备并且因此对它没有用,设备的 NIC 会丢弃该数据包,而不是将其传递给 CPU 进行处理。
丢弃不面向接收主机的数据包可以提高处理效率,但这对数据包分析员来说并不是那么理想。作为分析员,我们通常希望捕获通过网络传输的每个数据包,以免错过一些关键信息。
我们可以通过使用网卡的混杂模式来确保捕获所有流量。在混杂模式下,网卡会将它看到的每个数据包都传递给主机的处理器,无论地址如何。一旦数据包到达 CPU,数据包嗅探应用程序就可以将其抓取进行分析。
大多数现代网卡都支持混杂模式,而 Wireshark 包含 libpcap/WinPcap 驱动程序,允许它通过 Wireshark GUI 将网卡直接切换到混杂模式。(我们将在第三章中详细讨论 libpcap/WinPcap。)
本书要求你必须拥有支持使用混杂模式的网卡和操作系统。唯一不需要在混杂模式下嗅探的情况是,当你只想查看直接发送到你嗅探的接口的 MAC 地址的流量时。
注意
大多数操作系统(包括 Windows)不会允许你在没有提升用户权限的情况下使用网卡的混杂模式。如果你无法合法地获得这些权限,那么你很可能不应该在该网络上进行任何类型的数据包嗅探。
嗅探集线器网络
在安装了集线器的网络上进行嗅探是任何数据包分析师的梦想。正如你在第一章中学到的那样,集线器传输的流量会通过连接到该集线器的每个端口。因此,要分析通过连接到集线器的计算机的流量,你只需将数据包嗅探器连接到集线器上的空闲端口即可。你将能够看到该计算机的所有通信,以及连接到该集线器的任何其他设备之间的所有通信。如图 2-2 所示,当你的嗅探器连接到集线器网络时,您的可视窗口是无限的。

图 2-2:在集线器网络上嗅探提供了一个无限的可视窗口。
注意
如本书各个图表中所示,可视窗口表示网络上你可以用数据包嗅探工具看到流量的设备。
对我们来说,不幸的是,基于集线器的网络已经很少见,因为它们给网络管理员带来了很多麻烦。由于在任何时候只有一个设备可以通过集线器进行通信,连接的设备必须与所有其他试图通信的设备竞争带宽。当两个或更多设备同时通信时,数据包会发生冲突,如图 2-3 所示。结果可能是数据包丢失,通信设备可能会通过重新传输数据包来补偿丢失,从而增加网络拥塞。随着流量和冲突次数的增加,设备可能需要传输数据包三到四次,网络性能会显著下降。因此,很容易理解为什么大多数现代网络都使用交换机。虽然在现代网络中很少见到集线器,但在支持旧版硬件或特殊设备的网络中,例如工业控制系统(ICS)网络中,偶尔会遇到它们。

图 2-3:当两个或更多设备同时发送数据时,集线器网络会发生数据包冲突。
识别网络中是否使用集线器的最简单方法是查看服务器机房或网络机柜。大多数集线器上都会有标签。如果一切都失败了,只需在服务器机柜的最暗角落寻找那些布满几英寸灰尘的网络硬件。
在交换环境中的嗅探
交换机是现代网络中最常用的连接设备。它们通过广播、单播和多播流量提供高效的数据传输方式。交换机支持全双工通信,这意味着设备可以同时发送和接收数据。
对数据包分析师来说,不幸的是,交换机增加了复杂性。当你将嗅探器连接到交换机的端口时,你只能看到广播流量以及嗅探器所在设备发送和接收的流量,如图 2-4 所示。为了捕获交换网络中目标设备的流量,你需要采取额外的步骤。

图 2-4:在交换网络中,能看到的流量窗口仅限于你连接的端口。
捕获这些流量的四种主要方法是:端口镜像、集线器连接、使用网络采集器(tap)和 ARP 缓存中毒。
端口镜像
端口镜像,或称端口跨越,可能是捕获交换网络中目标设备流量的最简单方法。在这种设置中,你必须能够访问目标计算机所在交换机的命令行或网页管理界面。此外,交换机必须支持端口镜像并且具有一个空闲端口,以便你可以连接你的嗅探器。
要启用端口镜像,你需要发出一个命令,强制交换机将一个端口上的所有流量复制到另一个端口。例如,为了捕获从交换机的端口 3 发送和接收的所有流量,你可以将分析仪插入端口 4,并将端口 3 镜像到端口 4。图 2-5 展示了端口镜像的情况。

图 2-5:端口镜像允许你扩展交换网络中的可视窗口。
设置端口镜像的方式取决于交换机的制造商。对于大多数企业级交换机,你需要登录到命令行界面,并使用特定命令配置端口镜像。你可以在表 2-1 中找到一些示例的端口镜像命令。
表 2-1: 启用端口镜像的命令
| 制造商 | 命令 |
|---|---|
| Cisco | set span <source port> <destination port> |
| Enterasys | set port mirroring create <source port> <destination port> |
| Nortel | port-mirroring mode mirror-port <source port> monitor-port <destination port> |
注意
一些企业交换机提供基于 Web 的 GUI,提供端口镜像作为选项,但这些并不常见,且没有统一标准。然而,如果你的交换机提供了通过 GUI 配置端口镜像的有效方式,当然可以使用它。另外,更多的小型办公室和家庭办公室(SOHO)交换机开始提供端口镜像功能,通常是通过 GUI 配置的。
在进行端口镜像时,注意你正在镜像的端口的吞吐量。一些交换机制造商允许将多个端口镜像到一个端口,这在分析单个交换机上两个或更多设备之间的通信时可能非常有用。然而,让我们通过一些基本的数学来考虑可能发生的情况。如果你有一台 24 个端口的交换机,并将 23 个全双工 100Mbps 端口镜像到一个端口,那么这个端口的流量可能高达 4600Mbps。这远远超过了单个端口的物理阈值,因此,如果流量达到一定水平,可能会导致丢包或网络延迟。这种情况有时被称为超额订阅。在这些情况下,交换机可能会完全丢弃多余的包,甚至“暂停”其内部电路,导致通信中断。在进行捕获时,务必确保不会引发此类问题。
端口镜像可能看起来是一个有吸引力的低成本解决方案,适用于需要持续监控特定网络段的企业网络和场景,例如在网络安全监控中。然而,这种技术通常不足以在此类应用中提供足够的可靠性,尤其是在高吞吐量的情况下,端口镜像可能会提供不一致的结果,并导致数据丢失,难以追踪。在这种情况下,建议使用“使用 TAP”中讨论的 TAP,详见第 24 页。
通过集线器隔离
捕获通过目标设备的流量的另一种方法是在交换网络中使用集线器隔离。通过这种技术,你可以将目标设备和分析仪系统直接插入集线器,将它们放置在同一网络段。许多人将集线器隔离视为“作弊”,但当你无法执行端口镜像,并且仍能物理接触目标设备连接的交换机时,这实际上是一个有效的解决方案。
要进行集线器隔离,你只需要一个集线器和几根网络电缆。得到硬件后,按以下方式连接:
-
找到目标设备所在的交换机并将目标设备从网络中拔掉。
-
将目标设备的网络线插入到集线器中。
-
插入另一条连接分析仪与集线器的电缆。
-
将一根网络电缆从集线器插入到网络交换机,以将集线器连接到网络。
现在你已经将目标设备和分析仪放在同一广播域中,所有来自目标设备的流量将被广播,以便分析仪能够捕获这些数据包,如图 2-6 所示。

图 2-6:通过集线器隔离了目标设备和分析仪。
在大多数情况下,通过集线器隔离会将目标设备的双工模式从全双工(双向)减少到半双工(单向)。虽然这种方法不是捕获数据包最干净的方式,但当交换机不支持端口镜像时,有时它是你唯一的选择。但请记住,你的集线器也需要电源连接,而这可能很难找到。
注意
提醒一下,通常在拔掉设备前通知设备的用户是一个很好的举动,特别是当该用户恰好是公司的 CEO 时!
找到“真正的”集线器
在进行集线器隔离时,确保你使用的是一个真正的集线器,而不是错误标记的交换机。许多网络硬件供应商有一个坏习惯,将一种低级交换机标记并销售为“集线器”。如果你没有使用经过验证的集线器,你只会看到你自己的流量,而看不到目标设备的流量。
当你找到一个你认为是集线器的设备时,测试它以确保其功能。确定设备是否为真正集线器的最佳方法是将一对计算机连接到该设备,看看是否其中一台计算机能够嗅探到另一台计算机与网络上其他设备(如另一台计算机或打印机)之间的流量。如果能,你就找到了一个可靠的设备!
由于集线器(hubs)已经过时,现在几乎不再大规模生产了。几乎不可能在市面上买到真正的集线器,所以你需要发挥创造力才能找到一个。一个很好的来源通常是你当地学区举行的 surplus 拍卖。公立学校在处理剩余物品前必须尝试拍卖这些物品,它们通常会有一些旧硬件堆放在一旁。我见过有人在拍卖会上以低于一盘白豆和玉米面包的价格买到好几个集线器。或者,eBay 也是一个不错的集线器来源,但要小心,因为你可能会碰到标错的交换机。
使用 Tap
大家都知道“为什么吃鸡肉,而你可以吃牛排?”(或者,如果你来自南方,“为什么吃肝酱,而你可以吃炸香肠?”)这种选择同样适用于集线器与使用 tap 之间的对比。
网络tap是一种硬件设备,你可以将其放置在电缆系统的两个点之间,以捕获这两个点之间的数据包。与集线器(hubbing out)类似,你需要在网络中放置一台硬件设备,允许你捕获所需的数据包。不同之处在于,你不是使用集线器,而是使用一种专门为网络分析设计的硬件设备。
网络 tap 主要有两种类型:聚合型和非聚合型。这两种类型的 tap 都位于两台设备之间,用于嗅探通信。聚合型 tap 与非聚合型 tap 的主要区别在于,非聚合型 tap 有四个端口,如图 2-7 所示,需要独立的接口来监控双向流量,而聚合型 tap 只有三个端口,只需一个接口即可进行双向流量监控。

图 2-7:一款 Barracuda 非聚合型 tap
Tap 通常需要一个电源连接,尽管有些 tap 内置电池,允许进行短时间的数据包嗅探。
聚合型 Tap
聚合型 tap 是最简单的使用方式。它只有一个物理监控端口,适用于双向流量嗅探。
若要捕获从插入交换机的单台计算机的所有流量,请按照以下步骤操作:
-
从交换机上拔下计算机。
-
将一端的网络电缆插入计算机,另一端插入 tap 的“in”端口。
-
将另一端的网络电缆插入 tap 的“out”端口,另一端插入网络交换机。
-
将一端的电缆插入 tap 的“monitor”端口,另一端插入作为嗅探器的计算机。
聚合型 tap 应按照图 2-8 所示进行连接。此时,你的嗅探器应该已经捕获了所有进出你插入 tap 的计算机的流量。

图 2-8:使用聚合 tap 拦截网络流量
非聚合型 Tap
非聚合 tap 比聚合类型稍微复杂一些,但在捕获流量时提供了更多的灵活性。与聚合 tap 只有一个可用于监听双向通信的监视端口不同,非聚合 tap 具有两个监视端口。一个监视端口用于嗅探来自连接到 tap 的计算机的单向流量,另一个监视端口用于嗅探流向连接到 tap 的计算机的单向流量。
要捕获所有流入和流出单台计算机的流量,请按照以下步骤操作:
-
将计算机从交换机上拔掉。
-
将一根网线的一端插入计算机,另一端插入 tap 的“in”端口。
-
将另一根网线的一端插入到 tap 的“out”端口,另一端插入到网络交换机中。
-
将第三根网线的一端插入到 tap 的“monitor A”端口,另一端插入到充当嗅探器的计算机的一个 NIC 端口。
-
将一根网线的一端插入到 tap 的“monitor B”端口,另一端插入到充当嗅探器的计算机的第二个 NIC 端口。
非聚合 tap 应按照图 2-9 所示的方式连接。

图 2-9:使用非聚合 tap 拦截网络流量
虽然这些示例可能让你觉得只能通过 tap 监控单个设备,但实际上通过巧妙地放置 tap,你可以监控多个设备。例如,如果你想监控整个网络段与互联网之间的所有通信,可以将 tap 放置在连接所有其他设备的交换机与网络上游路由器之间。将 tap 放置在网络瓶颈点可以让你收集所需的流量。这种策略在安全监控中很常见。
选择网络 tap
哪种类型的 tap 更好?在大多数情况下,聚合 tap 更受欢迎,因为它们需要较少的布线,并且不需要在嗅探计算机上安装两个 NIC。然而,如果你需要捕获大量流量或只关心单向流量,非聚合 tap 则是更好的选择。
你可以购买各种大小的 tap,从简单的以太网 tap(大约 150 美元)到企业级光纤 tap(价格达到六位数)。我曾使用过 Ixia(前身为 Net Optics)、Dualcomm 和 Fluke Networks 的企业级 tap,效果非常好,但市场上也有许多其他优秀的 tap。如果你在企业应用中使用 tap,你需要确保 tap 具备故障开放功能。这意味着,如果 tap 发生故障或失效,数据包仍然会通过 tap 传输,且连接到 tap 的网络链路不会中断。
ARP 缓存中毒
我最喜欢的窃听技术之一就是 ARP 缓存中毒。我们将在第七章中详细讨论 ARP 协议,但在这里简要说明一下,以便你理解这种技术是如何工作的。
ARP 过程
回顾第一章,OSI 模型的第 2 层和第 3 层是两种主要的包地址类型。这些第 2 层地址,或称 MAC 地址,与您使用的任何第 3 层地址系统一起使用。在本书中,按照行业标准术语,我将第 3 层地址系统称为IP 地址系统。
网络上的所有设备都使用 IP 地址在第 3 层进行通信。由于交换机在 OSI 模型的第 2 层工作,它们只关心第 2 层的 MAC 地址,因此设备必须能够在构造的数据包中包含这些信息。当 MAC 地址未知时,必须通过已知的第 3 层 IP 地址获取,以便将流量转发到适当的设备。这一翻译过程是通过第 2 层协议 ARP 完成的。
对于连接到以太网网络的计算机,ARP 过程在一台计算机希望与另一台计算机通信时开始。发送计算机首先检查其 ARP 缓存,看看是否已经拥有与目标计算机的 IP 地址相关联的 MAC 地址。如果没有,它会发送一个 ARP 请求到数据链路层的广播地址 ff:ff:ff:ff:ff:ff,如第一章所讨论的那样。这个广播包会被该特定以太网段上的每台计算机接收。该包基本上是在询问:“哪个 IP 地址拥有 xx:xx:xx:xx:xx:xx MAC 地址?”
没有目标计算机 IP 地址的设备会直接丢弃这个 ARP 请求。目标计算机通过 ARP 回复包回复其 MAC 地址。此时,原始发送计算机现在拥有了与远程计算机通信所需的数据链路层地址信息,并将这些信息存储在其 ARP 缓存中,以便快速检索。
ARP 缓存中毒是如何工作的
ARP 缓存中毒,有时也叫做 ARP 欺骗,是一种在交换网络中窃听信号的高级技术。它通过向以太网交换机或路由器发送带有虚假 MAC(第 2 层)地址的 ARP 消息,来拦截另一台计算机的流量。图 2-10 展示了这一设置。

图 2-10:ARP 缓存中毒可以让你拦截目标计算机的流量。
这种技术通常被攻击者用来向客户端系统发送虚假地址的数据包,以拦截特定流量或对目标发起拒绝服务(DoS)攻击。然而,它也可以是捕获交换网络上目标机器数据包的一种合法方式。
使用 Cain & Abel
在尝试进行 ARP 缓存中毒时,第一步是获取必要的工具并收集一些信息。为了演示,我们将使用来自 oxid.it 的流行安全工具 Cain & Abel(* www.oxid.it/*),它支持 Windows 系统。按照网站上的指示下载并安装它。
注意
当你尝试下载 Cain & Abel 时,杀毒软件或浏览器很可能会将该软件标记为恶意软件或“黑客工具”。这个工具有多种用途,其中一些可能是恶意的。但在我们的使用中,它对你的系统没有威胁。
在你能使用 Cain & Abel 之前,你需要收集一些信息,包括分析器系统的 IP 地址、你希望捕获流量的远程系统的 IP 地址以及该远程系统下游的路由器。
当你第一次打开 Cain & Abel 时,你会注意到窗口顶部有一系列标签。(ARP 缓存中毒只是 Cain & Abel 的一个功能。)为了我们的目的,我们将在嗅探器标签下操作。当你点击这个标签时,你应该看到一个空表格,如图 2-11 所示。

图 2-11:Cain & Abel 主窗口中的嗅探器标签
要完成这个表格,你需要激活程序的内置嗅探器,并扫描你的网络以寻找主机。请按照以下步骤操作:
-
单击工具栏上从左侧数起的第二个图标,它类似于一个网络接口卡(NIC)。
-
系统会要求你选择一个你希望进行嗅探的接口。选择连接到你将执行 ARP 缓存中毒操作的网络的接口。如果这是你第一次使用 Cain & Abel,选择该接口并点击确定。否则,如果你之前在 Cain & Abel 中选择过一个接口,那么你的选择将会被保存,你需要再次点击 NIC 图标以选择接口。(确保按下该按钮以激活 Cain & Abel 内置的嗅探器。)
-
要建立一个可用主机列表,点击加号(+)按钮。MAC 地址扫描器对话框会出现,如图 2-12 所示。我的子网中的所有主机单选按钮应该被选中(或者如果需要,你可以指定一个地址范围)。点击确定继续。

图 2-12:使用 Cain & Abel 网络发现工具扫描 MAC 地址
一些 Windows 10 用户报告称 Cain & Abel 无法确定他们网络接口的 IP 地址,导致无法完成此过程。如果你遇到这个问题,在配置网络接口时你会看到接口的 IP 地址是 0.0.0.0。为了解决这个问题,请按照以下步骤操作:
-
如果 Cain & Abel 已打开,关闭它。
-
在桌面搜索栏中,输入 ncpa.cpl 以打开网络连接对话框。
-
右键点击你将要进行嗅探的网络接口,然后点击属性。
-
双击 Internet Protocol Version 4 (TCP/IPv4)。
-
点击 高级 按钮并选择 DNS 标签。
-
选中 使用此连接的 DNS 后缀进行 DNS 注册 旁边的复选框以激活它。
-
点击 OK 退出打开的对话框并重新启动 Cain & Abel。
网格现在应该填充了你附加网络上所有主机的列表,以及它们的 MAC 地址、IP 地址和厂商信息。这是你在设置 ARP 缓存中毒时将要使用的列表。
在程序窗口的底部,你应该看到一组标签,点击它们将带你进入嗅探器下的其他窗口。现在你已经构建了主机列表,你将从 APR(用于 ARP 中毒路由)标签开始工作。现在点击该标签切换到 APR 窗口。
一旦进入 APR 窗口,你将看到两个空表格。在你完成设置步骤后,上方的表格将显示涉及你 ARP 缓存中毒的设备,下方的表格将显示你中毒机器之间的所有通信。
要设置你的中毒过程,按照以下步骤操作:
-
点击屏幕上方的空白区域。然后点击程序标准工具栏上的加号(+)按钮。
-
出现的窗口有两个选择面板。在左侧,你会看到网络中所有可用主机的列表。如果你点击目标计算机的 IP 地址,右侧面板将显示网络中所有主机的列表,除了目标机器的 IP 地址。
-
在右侧面板中,点击目标机器上游路由器的 IP 地址,如 图 2-13 所示,然后点击 OK。现在,两个设备的 IP 地址应该已列在主应用窗口的上方表格中。
-
为完成该过程,点击标准工具栏上的黄黑色辐射符号。这将激活 Cain & Abel 的 ARP 缓存中毒功能,并允许你的分析系统成为目标系统与其上游路由器之间所有通信的中介。

图 2-13:选择你希望启用 ARP 缓存中毒的设备
你现在应该能够启动数据包嗅探器并开始分析过程。当你完成捕获流量后,只需再次点击黄黑色辐射符号以停止 ARP 缓存中毒。
关于 ARP 缓存中毒的警告
关于 ARP 缓存中毒的最后提醒:你应该非常清楚你实施此过程时系统的角色。例如,当目标设备是网络利用率非常高的设备时,不要使用此技术,比如一个与网络连接速度为 1Gbps 的文件服务器(尤其是当你的分析系统只提供 100Mbps 的连接时)。
当你使用本示例中展示的技术重新路由流量时,所有传输和接收的流量必须首先经过你的分析系统,因此使得你的分析系统成为通信过程中的瓶颈。这个重新路由的过程可能会对你正在分析的机器造成类似 DoS 攻击的效果,导致网络性能下降和分析数据错误。流量拥堵还可能阻止基于 SSL 的通信按预期工作。
注意
你可以通过使用一种叫做不对称路由的功能,避免所有流量都经过你的分析系统。如需了解更多关于这一技术的信息,请参阅 oxid.it 用户手册(www.oxid.it/ca_um/topics/apr.htm)。
在路由环境中的嗅探
所有在交换网络上截取数据的技术同样适用于路由网络。处理路由环境时,唯一需要特别考虑的重要因素是,当你在排查涉及多个网络段的问题时,嗅探器的布置位置至关重要。
正如你所学到的,一个设备的广播域会一直扩展,直到遇到路由器为止,这时流量会被传递到下一个上游路由器。当数据必须经过多个路由器时,分析所有路由器两侧的流量非常重要。
例如,考虑一下你可能在一个通过多个路由器连接的网络中遇到的问题。在这个网络中,每个网络段与上游网络段进行通信以存储和检索数据。在图 2-14 中,我们试图解决的问题是,下游子网网络 D 无法与网络 A 中的任何设备通信。

图 2-14:网络 D 中的一台计算机无法与网络 A 中的计算机通信。
如果你嗅探网络 D 中一台与其他网络设备通信有问题的设备流量,你可能会清楚地看到数据被传输到另一个网络段,但却看不到返回的数据。如果你重新考虑嗅探器的位置,并开始嗅探下一个上游网络段(网络 B)的流量,你将更清晰地了解发生了什么。这时,你可能会发现流量被网络 B 的路由器丢弃或错误路由。最终,这将引导你发现路由器配置的问题,经过修正后,解决了你更大的困境。虽然这个场景有些宽泛,但故事的教训是:在处理多个路由器和网络段时,你可能需要稍微移动嗅探器,以获取完整的图景并精确定位问题。
网络拓扑图
在我们讨论网络布置时,我们已经研究了几张网络拓扑图。网络拓扑图,或称网络示意图,展示了网络中的所有技术资源及其连接方式。
没有什么比可视化网络更能帮助你确定数据包嗅探器的部署位置。如果你有网络拓扑图,请随时带着它,因为它将在故障排除和分析过程中发挥重要作用。你甚至可以想要制作自己网络的详细图。记住,有时故障排除的一半工作就是确保你收集到了正确的数据。
嗅探器部署实践
我们已经看过了四种在切换环境中捕获网络流量的方法。如果我们考虑仅在单个设备上安装数据包嗅探应用程序并捕获该设备的流量(直接安装法),我们还可以再增加一种方法。考虑到这五种方法,确定哪种方法最合适可能有些混乱。表 2-2 提供了每种方法的一些基本指南。
作为分析员,我们需要尽可能隐秘。在一个理想的世界里,我们收集所需的数据而不留下任何痕迹。就像法医调查员不希望污染犯罪现场一样,我们也不希望污染捕获的网络流量。
表 2-2: 切换环境中的数据包嗅探指南
| 技术 | 指南 |
|---|---|
| 端口镜像 | • 不会在网络上留下痕迹,也不会生成额外的数据包。• 可以在不使客户端下线的情况下配置,非常方便用于镜像路由器或服务器端口。• 需要交换机的处理资源,并且在高吞吐量下可能不稳定。 |
| 通过集线器连接 | • 当你不担心暂时使主机下线时有效。• 当必须从多个主机捕获流量时无效,因为可能会发生冲突和丢包。• 在现代 100/1000Mbps 主机上可能会丢失数据包,因为大多数集线器的速度仅为 10Mbps。 |
| 使用分接器 | • 当你不担心暂时使主机下线时,这是理想选择。• 当需要嗅探光纤连接的流量时,这是唯一的选择。• 由于分接器可靠且可以扩展到高吞吐量链路,因此它是企业数据包捕获和持续监控的首选方案。• 由于分接器是为此任务专门设计的,并且能够支持现代网络速度,因此这种方法优于通过集线器进行捕获。• 可能会很昂贵,尤其是大规模部署时,可能会导致成本过高。 |
| ARP 缓存中毒 | • 被认为非常粗糙,因为它涉及将数据包注入网络,通过嗅探器重新路由流量。• 当端口镜像不可用时,可以快速有效地从设备捕获流量,而无需使其下线。• 需要非常小心,以免影响网络功能。 |
| 直接安装 | • 通常不推荐使用,因为如果主机出现问题,该问题可能会导致数据包丢失或被篡改,从而使其无法准确表示。 • 主机的网卡不需要处于混杂模式。 • 最适合测试环境、检查/基准性能以及检查在其他地方创建的捕获文件。 |
在后续章节中,我们将通过实际场景来讨论根据具体情况捕获所需数据的最佳方法。暂时,图表图 2-15 应该能帮助你选择在特定情况下捕获流量的最佳方法。该图表考虑了不同的因素,首先是你是在家里还是在工作中捕获数据包。请记住,这个流程图仅作为一般参考,并未涵盖所有可能的场景,尤其是你可能接入网络的情况。

图 2-15:帮助确定哪种方法最适合接入网络的图示
第三章:Wireshark 简介

如第一章所述,虽然有多种数据包嗅探应用可用于执行网络分析,但我们将在本书中主要关注 Wireshark。本章将介绍 Wireshark。
Wireshark 的简短历史
Wireshark 有着非常丰富的历史。Gerald Combs 是堪萨斯城密苏里大学的计算机科学毕业生,他最初出于必要性开发了 Wireshark。Combs 的第一个版本的应用程序,名为 Ethereal,于 1998 年发布,并采用了 GNU 公共许可证(GPL)。
发布《Ethereal》八年后,Combs 离职去追求其他职业机会。不幸的是,当时他的雇主拥有《Ethereal》商标的全部权利,Combs 未能达成协议,使他能够控制《Ethereal》品牌。最终,Combs 和其他开发团队成员于 2006 年中期将该项目重新命名为Wireshark。
Wireshark 的受欢迎程度大幅增长,目前其协作开发团队拥有超过 500 名贡献者。以 Ethereal 名称存在的程序不再被开发。
Wireshark 的优势
Wireshark 提供了几个使其在日常使用中很有吸引力的优势。它面向初学者和专家数据包分析师,提供了多种功能以吸引各类用户。让我们根据第一章中定义的标准,来评估 Wireshark 在选择数据包嗅探工具时的表现。
支持的协议 Wireshark 在支持的协议数量上表现突出——截至本文编写时,已支持超过 1,000 种协议。这些协议从常见的 IP 和 DHCP 到更高级的专有协议,如 DNP3 和 BitTorrent。由于 Wireshark 是在开源模式下开发的,每次更新时都会添加新的协议支持。
注意
如果 Wireshark 不支持您需要的协议,您可以自行编写代码来实现支持。然后,您可以将代码提交给 Wireshark 开发者,以供考虑是否纳入应用程序中。有关向 Wireshark 项目贡献代码的要求,您可以在 www.wireshark.org/develop.html 查看相关信息。
用户友好性 Wireshark 的界面是所有数据包嗅探应用中最容易理解的之一。它基于图形用户界面(GUI),具有清晰编写的上下文菜单和简洁的布局。它还提供了多种旨在提升可用性的功能,如基于协议的颜色编码和原始数据的详细图形表示。与一些更为复杂的基于命令行的替代工具(如 tcpdump)不同,Wireshark 的 GUI 对初学者也十分友好。
费用 由于 Wireshark 是开源的并且发布在 GNU 公共许可证(GPL)下,它的定价无可比拟:它完全免费。你可以出于任何目的下载和使用 Wireshark,无论是个人使用还是商业用途。
注意
尽管 Wireshark 可能是免费的,但一些人犯了一个错误,不小心付费购买了它。如果你在 eBay 上搜索数据包嗅探器,你可能会惊讶于有多少人愿意以 39.95 美元的低价卖给你一个“专业企业许可证”。如果你真的决定想要购买它,给我打个电话,我们可以谈谈我在肯塔基州待售的一块海滨地产!
程序支持 一个软件包的支持水平可能决定它的成败。像 Wireshark 这样的自由分发软件可能没有正式的技术支持,因此开源社区通常依赖于其用户基础提供帮助。幸运的是,Wireshark 社区是所有开源项目中最活跃的社区之一。Wireshark 网站直接链接到多种支持形式,包括在线文档;维基百科;常见问题解答;以及注册 Wireshark 邮件列表的地方,这些邮件列表通常由该程序的大部分顶级开发人员进行监控。Wireshark 的付费支持也可以通过 Riverbed Technology 提供。
源代码访问 Wireshark 是开源软件,因此你可以随时访问其源代码。这对于解决应用程序问题、理解协议分析器的工作原理,或进行自己的贡献都非常有用。
操作系统支持 Wireshark 支持所有主要的现代操作系统,包括 Windows、基于 Linux 的系统和 OS X 平台。你可以在 Wireshark 主页上查看完整的操作系统支持列表。
安装 Wireshark
Wireshark 的安装过程出奇的简单。然而,在安装 Wireshark 之前,请确保你的系统满足以下要求:
• 任意现代的 32 位 x86 或 64 位 CPU
• 400MB 可用内存,但如果是较大的捕获文件,内存需求更高
• 至少需要 300MB 的可用存储空间,另外还需要存储捕获文件的空间
• 支持混杂模式的网卡
• WinPcap/libpcap 捕获驱动程序
WinPcap 捕获驱动程序是 Windows 系统上实现的 pcap 数据包捕获应用程序接口(API)。简而言之,这个驱动程序与操作系统交互,捕获原始数据包数据,应用过滤器,并将网卡在混杂模式和正常模式之间切换。
尽管你可以单独下载 WinPcap(从 www.winpcap.org/),但通常更好的做法是从 Wireshark 安装包中安装 WinPcap,因为该版本的 WinPcap 已通过测试,确保能够与 Wireshark 兼容。
在 Windows 系统上安装
当前版本的 Wireshark 已测试支持仍在延长支持生命周期内的 Windows 版本。截至本书编写时,这些版本包括 Windows Vista、Windows 7、Windows 8、Windows 10,以及 Windows Servers 2003、2008 和 2012。虽然 Wireshark 通常也可以在其他版本的 Windows(如 Windows XP)上运行,但这些版本不被正式支持。
在 Windows 上安装 Wireshark 的第一步是从官方 Wireshark 网页获取最新的安装包,* www.wireshark.org/*。访问网站上的下载 Wireshark 部分并选择一个镜像。下载完安装包后,按照以下步骤操作:
-
双击 .exe 文件以开始安装,然后在介绍窗口中点击 下一步。
-
阅读许可协议并点击 我同意,如果你同意的话。
-
选择你希望安装的 Wireshark 组件,如 图 3-1 所示。对于我们的目的,你可以通过点击 下一步 来接受默认设置。
![image]()
图 3-1:选择你希望安装的 Wireshark 组件
-
在附加任务窗口中点击 下一步。
-
选择你希望安装 Wireshark 的位置,并点击 下一步。
-
当对话框询问是否要安装 WinPcap 时,首先确保勾选了安装 WinPcap框,如 图 3-2 所示。然后点击 安装。安装过程应会开始。
-
在 Wireshark 安装过程中大约一半时,WinPcap 安装应会开始。当它开始时,在介绍窗口中点击 下一步,阅读许可协议,并点击 我同意。
-
系统会提供安装 USBPcap 的选项,这是一个用于从 USB 设备收集数据的工具。如果你希望安装,请勾选相应的复选框,然后点击 下一步。
![image]()
图 3-2:选择安装 WinPcap 驱动程序的选项
-
WinPcap 和(如果你选择了的话)USBPcap 应该已经安装在你的计算机上。安装完成后,点击 完成。
-
Wireshark 应该完成安装。当它完成时,点击 下一步。
-
在安装确认窗口中,点击 完成。
在 Linux 系统上安装
Wireshark 可以在大多数现代基于 Unix 的平台上运行。它可以通过使用发行版的包管理器或下载并安装适合你发行版的包进行安装。由于无法覆盖所有安装过程,我们这里只讨论几种常见的情况。
通常,对于系统范围的软件,根权限是必需的。然而,从源代码编译的本地软件安装通常可以不需要根权限。
基于 RPM 的系统
如果你正在使用 Red Hat Linux 或基于它的发行版,比如 CentOS,那么操作系统很可能默认安装了 Yum 包管理工具。如果是这种情况,你可能可以通过从发行版的软件仓库中获取 Wireshark 来快速安装它。为此,打开一个控制台窗口并输入以下命令:
$ sudo yum install wireshark
如果需要任何依赖项,系统会提示你安装它们。如果一切顺利完成,你应该能够从命令行运行 Wireshark,并通过 GUI 访问它。
基于 DEB 的系统
大多数基于 DEB 的发行版,如 Debian 或 Ubuntu,包含 APT 包管理工具,允许你从操作系统的软件仓库中安装 Wireshark。要使用此工具安装 Wireshark,请打开一个控制台窗口并输入以下命令:
$ sudo apt-get install wireshark wireshark-qt
再次,你会被提示安装任何所需的依赖项以完成安装。
从源代码编译
由于操作系统架构和 Wireshark 功能的变化,从源代码编译 Wireshark 的指令可能会随着时间的推移发生变化。这也是推荐使用操作系统的包管理工具来执行安装的原因之一。然而,如果你的 Linux 发行版不使用自动化包管理软件,或者你需要特殊的安装方式,可以通过从源代码编译来手动安装 Wireshark。为此,请完成以下步骤:
-
从 Wireshark 网站下载源代码包。
-
通过输入以下命令解压归档文件(根据需要替换下载包的文件名):
$ tar –jxvf <file_name_here>.tar.bz2 -
在配置和安装 Wireshark 之前,根据你选择的 Linux 版本,可能需要一些依赖项。例如,Ubuntu 14.04 需要安装一些其他软件包才能正常运行 Wireshark。这些可以通过发出以下命令安装(你需要以 root 用户身份执行此操作,或者在命令前加上
sudo):$ sudo apt-get install pkg-config bison flex qt5-default libgtk-3-dev libpcap-dev qttools5-dev-tools -
安装完先决条件后,导航到提取 Wireshark 文件的目录。
-
使用命令
./configure配置源代码,使其能够正确地为你的 Linux 发行版编译。如果你希望偏离默认的安装选项,可以在此时指定这些选项。如果缺少任何依赖项,你很可能会收到错误消息。在继续之前,必须安装并配置这些依赖项。如果配置成功,你应该看到一条成功的消息,如 图 3-3 所示。![image]()
图 3-3:当
./configure命令成功执行时,会显示一条消息,提示已选择的配置。 -
输入 make 命令将源代码编译成二进制文件。
-
使用 sudo make install 启动最终安装。
-
运行 sudo/sbin/ldconfig 完成安装。
注意
如果你在按照这些步骤操作时遇到错误,可能需要安装一个额外的软件包。
在 OS X 系统上安装
在 OS X 上安装 Wireshark,请按照以下步骤操作:
-
从 Wireshark 的网页上下载 OS X 包。
-
运行安装工具并按照其步骤进行操作。一旦你接受了所需的最终用户许可协议,你将有机会选择安装位置。
-
完成安装向导。
Wireshark 基础知识
一旦你成功地在系统上安装了 Wireshark,你就可以开始熟悉它。现在,你终于可以打开你的功能齐全的数据包嗅探器,并看到……完全什么都没有!
好吧,Wireshark 在你第一次打开它时并不太吸引人。要让事情变得更有趣,你需要获取一些数据。
你的第一次数据包捕获
为了将数据包数据导入 Wireshark,你将进行第一次数据包捕获。你可能会想,“如果网络上没有问题,我怎么捕获数据包呢?”
首先,网络上总是存在问题。如果你不相信我,那就给你的网络用户发一封邮件,让他们知道一切都运行得完美无缺。
其次,不一定需要出现问题才能进行数据包分析。事实上,大多数数据包分析师花费更多时间分析没有问题的流量,而不是他们正在排查故障的流量。毕竟,你需要有一个基线来比较,才能有效地排查网络流量。例如,如果你希望通过分析 DHCP 流量来解决 DHCP 的问题,你必须了解工作正常的 DHCP 流量的流向。
更广泛地说,要在日常网络活动中发现异常,你必须了解正常的日常网络活动是什么样的。当你的网络运行顺利时,你的观察会成为一个基线,代表正常状态下的流量。
好吧,让我们捕获一些数据包吧!
-
打开 Wireshark。
-
从主下拉菜单中选择捕获,然后选择选项。你应该会看到一个对话框,列出了可以用于捕获数据包的各种接口,以及每个接口的基本信息(图 3-4)。注意流量标题,它显示了一个折线图,表示当前通过该接口的流量量。折线上的峰值告诉你,实际上你正在捕获数据包。如果没有数据包,线条会是平的。你还可以通过点击每个接口左侧的箭头来展开它,查看与之关联的地址信息,如 MAC 地址或 IP 地址。
-
点击你希望使用的接口,然后点击开始。数据应该开始填充窗口。
-
等待大约一分钟,当你准备停止捕获并查看数据时,从捕获下拉菜单中点击停止按钮。

图 3-4:选择用于执行数据包捕获的接口
一旦完成这些步骤并结束捕获过程,Wireshark 主窗口应该会充满数据。事实上,您可能会被出现的数据量压倒,但当我们逐一解析 Wireshark 的主窗口时,这一切都会很快变得有意义。
Wireshark 主窗口
您将大部分时间都花在 Wireshark 的主窗口中。这里展示了您捕获的所有数据包,并将它们分解成更易于理解的格式。使用您刚刚捕获的数据包,让我们来看一下 Wireshark 的主窗口,如图 3-5 所示。

图 3-5:Wireshark 的主窗口使用了三面板设计。
主窗口中的三个面板——从上到下的数据包列表、数据包详细信息和数据包字节——彼此相互依赖。要查看数据包详细信息面板中单个数据包的详细信息,必须先在数据包列表面板中选择该数据包。当你在数据包详细信息面板中选择数据包的某一部分时,数据包字节面板将显示与该部分相对应的字节。
注意
注意,图 3-5 在数据包列表面板中列出了几种不同的协议。不同层次的协议之间没有视觉上的分隔(除了通过颜色编码);所有数据包都按照接收到的顺序显示。
以下是每个面板的内容:
数据包列表 顶部面板显示了当前捕获文件中所有数据包的表格。它包含了数据包编号、数据包捕获的相对时间、数据包的源和目的地、数据包的协议以及数据包中找到的一些一般信息的列。
注意
当我提到流量时,我指的是在数据包列表面板中显示的所有数据包。当我特别提到DNS 流量时,我指的是数据包列表面板中的 DNS 协议数据包。
数据包详细信息 中间的面板显示了关于单个数据包的层次信息,并且可以折叠或展开以显示关于该数据包的所有收集信息。
数据包字节 下方面板——可能是最让人困惑的——显示数据包的原始未处理形式;也就是说,它展示了数据包在网络上传输时的样子。这是原始信息,没有任何温和或模糊的部分来使其更容易理解。我们将在附录 B 中讨论如何解释这类数据。
Wireshark 偏好设置
Wireshark 有多个可以自定义的偏好设置,以满足您的需求。要访问 Wireshark 的偏好设置,请从主下拉菜单中选择编辑并点击偏好设置。您将看到包含多个可自定义选项的偏好设置对话框,如图 3-6 所示。
Wireshark 的偏好设置分为六个主要部分,外加一个高级部分:
外观 这些设置决定了 Wireshark 如何呈现数据。你可以根据个人喜好在这里更改大多数选项,包括是否保存窗口位置、三大窗格的布局、滚动条位置、数据包列表窗格列的位置、用于显示捕获数据的字体,以及背景和前景颜色。

图 3-6:你可以使用“设置”对话框选项来自定义 Wireshark。
捕获 这些设置允许你指定与数据包捕获方式相关的选项,包括默认的捕获接口,是否默认使用混杂模式,以及是否实时更新“数据包列表”窗格。
过滤表达式 稍后我们将讨论 Wireshark 如何根据特定条件过滤流量。此部分设置允许你创建和管理这些过滤器。
名称解析 通过这些设置,你可以启用 Wireshark 的某些功能,使其能够将地址解析为更易识别的名称(包括 MAC、网络和传输名称解析),并指定最大并发名称解析请求数。
协议 这一部分允许你操作与 Wireshark 解码不同数据包相关的捕获和显示选项。并非每种协议都有可配置的设置,但有些协议提供了若干可以更改的选项。除非你有特定理由更改它们,否则最好保留默认设置。
统计信息 这一部分提供了 Wireshark 统计功能的一些可配置选项,这些内容将在第五章中详细介绍。
高级 不适合归入上述任何类别的设置可以在此找到。编辑这些设置通常是 Wireshark 高级用户的工作。
数据包颜色编码
如果你像我一样,喜欢闪亮的物体和漂亮的颜色,那么当你在“数据包列表”窗格中看到这些不同的颜色时,可能会感到很兴奋,就像在图 3-7 中的示例一样(如果你是看纸质书,图示是黑白的,但你大概明白我的意思)。这些颜色似乎是随机分配给每个数据包的,但事实并非如此。

图 3-7:Wireshark 的颜色编码可以快速识别协议。
每个数据包会以特定的颜色显示,原因是有的。颜色可以反映数据包的协议和特定字段值。例如,所有的 UDP 流量默认是蓝色,所有的 HTTP 流量默认是绿色。颜色编码使你能够快速区分不同的协议,因此你无需每次都在“数据包列表”窗格中读取协议字段。你会发现,这大大加快了浏览大文件时所需的时间。
Wireshark 通过着色规则窗口使你能够轻松查看每个协议分配的颜色,如图 3-8 所示。要打开此窗口,请从主下拉菜单选择 查看 并点击 着色规则。

图 3-8:着色规则窗口让你查看和修改数据包的着色。
着色规则基于 Wireshark 过滤器,我们将在第四章中讨论这些过滤器。使用这些过滤器,你可以定义自己的着色规则并修改现有的规则。例如,要将 HTTP 流量的背景颜色从默认的绿色改为薰衣草色,请按照以下步骤操作:
-
打开 Wireshark 并访问着色规则窗口(查看 ▶ 着色规则)。
-
在着色规则列表中找到 HTTP 着色规则并单击选择它。
-
你将在屏幕底部看到前景色和背景色,如图 3-9 所示。
![image]()
图 3-9:编辑颜色过滤器时,你可以修改前景色和背景色。
-
点击 背景 按钮。
-
选择你希望在颜色轮上使用的颜色并点击 确定。
-
再次点击 确定 接受更改并返回主窗口。用户界面将重新加载,以反映更新后的颜色方案。
当你在网络上使用 Wireshark 时,会开始注意到某些协议比其他协议更常见。此时,颜色编码的数据包可以让你的工作变得更加轻松。例如,如果你认为网络上存在一个不明的 DHCP 服务器在分发 IP 租约,你可以修改 DHCP 协议的着色规则,使其显示为亮黄色(或其他易于识别的颜色)。这样,你就能更快地识别出所有的 DHCP 流量,提高数据包分析的效率。
注意
不久前,我在向本地学生小组做演讲时讨论了 Wireshark 着色规则。一位学生发现自己可以编辑着色规则时松了一口气,因为他是色盲,基于默认着色很难区分某些协议。因此,能够修改默认的着色规则为一些程度的可访问性提供了帮助。
配置文件
了解 Wireshark 存储各种配置设置的位置非常有帮助,尤其是当你需要直接修改这些文件时。你可以通过从主下拉菜单选择 帮助,选择 关于 Wireshark,然后点击 文件夹 标签来查找 Wireshark 配置文件的位置。此窗口如图 3-10 所示。

图 3-10:定位 Wireshark 配置文件
在 Wireshark 定制中,最重要的两个位置是个人配置目录和全局配置目录。全局配置目录包含 Wireshark 的所有默认设置,并且是默认配置文件存储其设置的地方。个人配置文件夹包含针对你的帐户定制的设置和配置文件。你创建的任何新配置文件将存储在个人配置文件夹的子目录中,并使用你提供的名称。
全局配置目录和个人配置目录之间的区别非常重要,因为对全局配置文件所做的任何更改都会影响系统上的每个 Wireshark 用户。
配置文件
在了解 Wireshark 的偏好设置后,你可能会发现,有时你想使用一组偏好设置,但又希望迅速切换到另一组以应对不同的场景。Wireshark 引入了配置文件,允许用户创建已保存的偏好设置集,而不必每次发生这种情况时都手动重新配置偏好设置。
配置文件存储以下内容:
• 偏好设置
• 捕获过滤器
• 显示过滤器
• 着色规则
• 禁用的协议
• 强制解码
• 最近的设置,例如面板大小、视图菜单设置和列宽
• 特定协议的表格,例如 SNMP 用户和自定义 HTTP 头
要查看配置文件列表,可以在主下拉菜单中点击编辑并选择配置文件选项。或者,你也可以右键点击屏幕右下角的配置文件部分,选择管理配置文件选项。当你进入配置文件窗口时,你会看到 Wireshark 提供了一些标准配置文件,包括图 3-11 中显示的默认、蓝牙和经典配置文件。延迟调查配置文件是我添加的自定义配置文件,采用的是纯文本格式,而全局和默认配置文件则以斜体显示。

图 3-11:查看配置文件
配置文件窗口允许你创建、复制、删除和应用配置文件。创建新配置文件的过程非常简单。
-
根据你希望保存到配置文件中的设置配置 Wireshark。
-
通过在主下拉菜单中点击编辑,进入配置文件窗口。选择配置文件选项。
-
点击加号(+)按钮,并为配置文件指定一个描述性名称。
-
点击确定。
当你想切换配置文件时,可以进入配置文件窗口,点击配置文件名称,然后点击确定。你也可以通过点击 Wireshark 窗口右下角的 Profile 标题,并选择你想使用的配置文件来更快地完成此操作,如图 3-12 所示。

图 3-12:通过 Profile 标题快速切换配置文件。
配置文件最有用的一个方面是,每个配置文件都保存在其独立的目录中,并包含一系列配置文件。这意味着你可以备份配置文件并与他人分享。图 3-10 中的文件夹标签提供了个人和全局配置文件目录的路径。要与另一台计算机上的用户共享配置文件,只需复制与要共享的配置文件同名的文件夹,并将其粘贴到另一台计算机上相应用户的同一目录中。
在阅读本书时,你可能会发现需要创建一些高层次的配置文件,以进行常规故障排除、查找网络延迟源头以及调查安全问题。不要害怕广泛使用配置文件。当你想要快速切换一些偏好设置时,配置文件能为你节省大量时间。我认识一些人,他们成功地使用了数十个配置文件来应对不同的场景。
现在你已经成功启动了 Wireshark,准备进行数据包分析。第四章描述了如何处理你捕获到的数据包。
第四章:处理捕获的数据包

现在你已经了解了 Wireshark,准备开始捕获和分析数据包了。在本章中,你将学习如何处理捕获文件、数据包和时间显示格式。我们还将介绍更多关于捕获数据包的高级选项,并深入了解过滤器的使用。
处理捕获文件
你会发现,你的大部分数据包分析会发生在捕获之后。通常,你会在不同的时间进行几次捕获,保存它们,并一次性分析它们。因此,Wireshark 允许你将捕获的文件保存以便稍后分析。你还可以合并多个捕获文件。
保存和导出捕获文件
要保存数据包捕获,选择文件 ▶ 另存为。你将看到“保存文件为”对话框,如图 4-1 所示。系统会要求你指定保存捕获文件的位置和希望使用的文件格式。如果没有指定文件格式,Wireshark 将使用默认的 .pcapng 格式。

图 4-1: “保存文件为”对话框允许你保存数据包捕获。
在许多情况下,你可能只想保存捕获中的一部分数据包。要做到这一点,选择文件 ▶ 导出指定数据包。出现的对话框如图 4-2 所示。这是精简冗长数据包捕获文件的好方法。你可以选择仅保存某个数字范围内的数据包、标记的数据包,或者作为显示过滤结果可见的数据包(标记的数据包和过滤器将在本章后面讨论)。
你可以将 Wireshark 捕获的数据导出为几种格式,以便在其他媒体中查看或导入到其他数据包分析工具中。这些格式包括纯文本、PostScript、逗号分隔值 (CSV) 和 XML。要以其中一种格式导出数据包捕获,选择文件 ▶ 导出数据包解析,然后选择导出文件的格式。你将看到一个“另存为”对话框,其中包含与你选择的格式相关的选项。

图 4-2: “导出指定数据包”对话框让你可以更精确地控制你选择保存的数据包。
合并捕获文件
某些类型的分析需要合并多个捕获文件的能力。这通常是在比较两个数据流或将分别捕获的相同流量数据合并时使用的做法。
要合并捕获文件,打开其中一个你想要合并的文件,然后选择文件 ▶ 合并,以打开“合并捕获文件”对话框,如图 4-3 所示。选择你希望合并到当前打开文件的新文件,然后选择合并文件的方法。你可以将选定文件添加到当前文件前面、后面,或者根据时间戳按时间顺序合并文件。

图 4-3:与捕获文件合并对话框允许你合并两个捕获文件。
处理数据包
你最终会遇到涉及大量数据包的情况。随着数据包数量的增长,达到几千甚至几百万个数据包,你需要更高效地浏览这些数据包。为此,Wireshark 允许你查找并标记符合特定标准的数据包。你还可以打印数据包以方便参考。
查找数据包
要查找符合特定标准的数据包,请通过按 CTRL-F 打开查找数据包栏,如图 4-4 中圈出的部分所示。该栏应出现在过滤器栏和数据包列表面板之间。

图 4-4:在 Wireshark 中根据指定的标准查找数据包——在这种情况下,是符合显示过滤器表达式 tcp 的数据包
这个面板提供了三种查找数据包的选项:
• 显示过滤器选项允许你输入基于表达式的过滤器,该过滤器将只查找满足该表达式的数据包。此选项在图 4-4 中使用。
• 十六进制值选项可以搜索你指定的十六进制值的数据包。
• 字符串选项搜索包含你指定文本字符串的数据包。你可以指定搜索执行的面板,或者使搜索字符串区分大小写。
表 4-1 展示了这些搜索类型的示例。
表 4-1: 查找数据包的搜索类型
| 搜索类型 | 示例 |
|---|---|
| 显示过滤器 | not ip ip.addr==192.168.0.1 arp |
| 十六进制值 | 00ff ffff 00ABB1f0 |
| 字符串 | Workstation1 UserB domain |
一旦决定使用哪种搜索类型,就在文本框中输入搜索标准,并点击查找以查找第一个符合标准的数据包。要查找下一个匹配的数据包,再次点击查找或按 CTRL-N;要查找前一个匹配的数据包,请按 CTRL-B。
标记数据包
在找到符合标准的数据包后,你可以标记那些特别感兴趣的数据包。例如,标记数据包可以让你只保存这些数据包。此外,你还可以通过其黑色背景和白色文本快速找到你的标记数据包,如图 4-5 所示。

图 4-5:屏幕上突出显示了一个标记的包。在这个例子中,第二个包被标记并显示为较暗。
要标记数据包,可以右键点击数据包列表面板中的数据包,然后从弹出菜单中选择标记数据包,或点击数据包并按 CTRL-M。要取消标记数据包,再次按 CTRL-M 可以切换此设置。你可以在一个捕获中标记任意数量的数据包。要在标记的数据包之间跳转,可以分别按 SHIFT-CTRL-N 和 SHIFT-CTRL-B。
打印数据包
尽管大多数分析将在计算机屏幕上进行,您可能需要打印捕获的数据。我偶尔会打印出数据包并将其贴在桌子上,这样在进行其他分析时可以快速参考其内容。能够将数据包打印成 PDF 文件也非常方便,尤其是在准备报告时。
要打印捕获的数据包,请通过主菜单选择文件 ▶ 打印打开打印对话框,如图 4-6 所示。

图 4-6:打印对话框允许您打印指定的数据包。
与“导出指定数据包”对话框类似,您可以打印特定的数据包范围、仅标记的数据包或作为过滤结果显示的数据包。您还可以选择每个数据包的打印详细程度。一旦选择好选项,点击打印。
设置时间显示格式和参考
时间至关重要——尤其是在数据包分析中。网络上的一切活动都是时间敏感的,您需要频繁地检查捕获文件中的趋势和网络延迟。Wireshark 提供了多个与时间相关的可配置选项。在本节中,我们将探讨时间显示格式和参考。
时间显示格式
Wireshark 捕获的每个数据包都会被赋予一个时间戳,该时间戳由操作系统应用于数据包。Wireshark 可以显示绝对时间戳,表示数据包捕获的确切时刻,以及与上一个捕获的数据包和捕获的开始与结束时间的关系。
与时间显示相关的选项位于主菜单中的“视图”项下。时间显示格式部分,如图 4-7 所示,允许您配置时间显示格式以及时间显示的精度。

图 4-7:提供多种时间显示格式。
显示格式选项允许您选择不同的时间显示设置。这些设置包括日期和时间、UTC 日期和时间、纪元以来的秒数、捕获开始以来的秒数(默认设置)、上一个捕获的数据包以来的秒数等等。
精度选项允许您将时间显示精度设置为自动设置,从捕获文件获取格式,或者设置为手动设置,如秒、毫秒、微秒等。我们将在书中的后面部分更改这些选项,因此您现在应该熟悉它们。
注意
在比较来自多个设备的数据包时,请确保这些设备与相同的时间源同步,特别是当您进行法医分析或故障排除时。您可以使用网络时间协议(NTP)确保网络设备同步。当检查来自跨越多个时区的设备的数据包时,考虑以 UTC 时间分析数据包,而非本地时间,以避免在报告发现时产生混淆。
数据包时间参考
数据包时间参考允许你配置某个数据包,使得所有后续的时间计算都相对于该数据包进行。当你检查一系列在捕获文件开始之外的某个时间点触发的顺序事件时,这个功能尤其有用。
要将时间参考设置为某个数据包,右键单击数据包列表窗格中的参考数据包并选择设置/取消时间参考。要关闭此参考,请重复相同的操作。你还可以通过在数据包列表窗格中选择你希望作为参考的数据包并按 CTRL-T 来切换数据包的时间参考。
当你在数据包上启用时间参考时,数据包列表窗格中的时间列将显示*REF*,如图 4-8 所示。

图 4-8:启用数据包时间参考切换的第 4 个数据包
设置数据包时间参考只有在捕获的时间显示格式设置为相对于捕获开始时间显示时才有用。任何其他设置将无法产生可用的结果,实际上会生成一组非常混乱的时间。
时间偏移
在某些情况下,你可能会遇到来自多个源的数据包,它们并未同步到相同的时间源。当检查从两个位置捕获的文件时,尤其常见,其中包含相同数据流的捕获。尽管大多数管理员希望网络上的每个设备都同步,但某些类型的设备之间可能会有几秒钟的时间偏差。Wireshark 提供了调整数据包时间戳的功能,可以在分析过程中缓解这个问题。
要调整一个或多个数据包的时间戳,选择编辑 ▶ 时间偏移,或者按下 CTRL-SHIFT-T。在打开的时间偏移屏幕上,你可以指定一个时间范围来调整整个捕获文件,或者你可以指定一个时间来设置单个数据包的时间戳。在图 4-9 中,我选择通过为每个数据包增加两分钟五秒来调整捕获中每个数据包的时间戳。

图 4-9:时间偏移对话框
设置捕获选项
在上章的简单数据包捕获过程中,我们曾讨论过捕获接口对话框。Wireshark 还提供了许多额外的捕获选项,但我们当时没有提到。要访问这些选项,请选择捕获 ▶ 选项。
捕获接口对话框有很多功能,旨在为你在捕获数据包时提供更多灵活性。它分为三个标签页:输入、输出和选项。我们将分别讨论每一个。
输入标签
输入选项卡 (图 4-10) 的主要目的是显示所有可用的捕获接口,并提供每个接口的一些基本信息。这些信息包括操作系统提供的接口友好名称、显示接口流量的图表,以及其他配置选项,如混杂模式状态和缓冲区大小。在最右侧(未显示)还有一个列,显示应用的捕获过滤器,稍后我们会在 第 65 页的“捕获过滤器”中讨论。
在本节中,你可以点击这些选项中的大多数,并直接进行编辑。例如,如果你想禁用某个接口的混杂模式,可以点击该字段,通过提供的下拉菜单将其从启用状态更改为禁用状态。

图 4-10:捕获接口输入选项卡
输出选项卡
输出选项卡 (图 4-11) 允许你自动将捕获的报文存储到文件中,而不是先捕获报文然后再保存文件。这样做为你提供了更多的灵活性来管理报文的保存方式。你可以选择将它们保存为单个文件或文件集,甚至可以使用环形缓冲区(稍后我们会介绍)来管理创建的文件数量。要启用此选项,请在文件文本框中输入完整的文件路径和名称。或者,使用浏览...按钮选择目录并提供文件名。

图 4-11:捕获接口输出选项卡
当你捕获大量流量或进行长期捕获时,文件集特别有用。文件集是由多个文件组成的集合,这些文件通过特定条件进行分隔。要保存到文件集,请勾选 在...之后自动创建新文件 选项。
Wireshark 使用各种触发器来基于文件大小或时间条件管理文件集保存。要启用这些触发器之一,选择大小或基于时间的选项旁边的单选按钮,然后指定触发的值和单位。例如,你可以设置一个触发器,在每捕获 1MB 流量后创建一个新文件,或者如 图 4-12 所示,在每捕获 1 分钟的流量后创建一个新文件。

图 4-12:Wireshark 在每分钟间隔创建的文件集
"使用环形缓冲区"选项允许你指定在 Wireshark 开始覆盖文件之前,文件集能保存的文件数量。虽然“环形缓冲区”一词有多种含义,但在我们的应用中,它本质上是一个文件集,指定一旦保存的最后一个文件写入完成,当需要保存更多数据时,第一个文件会被覆盖。换句话说,它建立了一种先进先出(FIFO)文件写入方法。你可以勾选此选项并指定希望循环使用的最大文件数量。例如,假设你选择为捕获使用多个文件,每小时创建一个新文件,并将环形缓冲区设置为 6。第六个文件创建完成后,环形缓冲区将会回绕并覆盖第一个文件,而不是创建第七个文件。这确保了最多只有六个文件(或在此情况下,六个小时)的数据保存在硬盘上,同时仍允许新数据被写入。
最后,输出标签还允许你指定是否使用.pcapng文件格式。如果你计划使用无法解析.pcapng格式的工具来处理保存的数据包,可以选择传统的.pcap格式。
选项标签
选项标签包含其他一些数据包捕获选项,包括显示、名称解析和捕获终止选项,详见图 4-13。

图 4-13:捕获接口选项标签
显示选项
显示选项部分控制捕获过程中数据包的显示方式。"实时更新数据包列表"选项不言自明,可以与"实时捕获时自动滚动"选项配对使用。当这两个选项都启用时,所有捕获的数据包都会显示在屏幕上,最新捕获的数据包会立即显示。
警告
当这两个选项配对使用时,即使你只捕获少量数据,它们也可能会消耗较多的处理器资源。除非你有特定需要实时查看数据包,否则最好取消勾选这两个选项。
"显示额外的捕获信息对话框"选项让你启用或抑制一个小窗口的显示,该窗口显示已捕获的数据包数量及其按协议分类的百分比。我喜欢显示捕获信息对话框,因为我通常不允许在捕获过程中实时滚动数据包。
名称解析设置
名称解析部分的选项允许你启用自动的 MAC(第二层)、网络(第三层)和传输(第四层)名称解析功能。我们将在第五章中更深入地讨论名称解析这一主题,包括它的缺点。
停止捕获设置
“在...之后自动停止捕获”部分让你在满足某些条件时停止正在进行的捕获。与多个文件集一样,你可以根据文件大小和时间间隔触发停止捕获,也可以基于数据包数量触发停止。这些选项可以与输出选项卡上的多文件选项一起使用。
使用过滤器
过滤器允许你指定可供分析的包。简单来说,过滤器是一个表达式,用于定义包的包含或排除标准。如果你不希望看到某些包,可以写一个过滤器将它们去除。如果你只希望看到特定的包,可以写一个过滤器仅显示这些包。
Wireshark 提供了两种主要的过滤器类型:
• 捕获过滤器 在捕获数据包时指定,只会捕获那些在给定表达式中指定为包含/排除的数据包。
• 显示过滤器 被应用于已捕获的数据包集,用于根据指定的表达式隐藏不需要的包或显示所需的包。
让我们先来看一下捕获过滤器。
捕获过滤器
捕获过滤器在数据包捕获过程中应用,用于从一开始就限制交付给分析员的数据包。使用捕获过滤器的一个主要原因是性能。如果你知道某种类型的流量不需要分析,你可以通过捕获过滤器简单地过滤掉它,从而节省通常用于捕获这些包的处理能力。
在处理大量数据时,创建自定义捕获过滤器非常有用。通过确保只查看与当前问题相关的包,可以加快分析速度。
例如,假设你正在排查一个运行在 262 端口的服务问题,但你正在分析的服务器在多个端口上运行着不同的服务。仅找到并分析某一个端口的流量本身就是一项工作。为了只捕获特定端口的流量,你可以使用捕获过滤器。具体做法是,使用捕获接口对话框,如下所示:
-
选择你希望捕获数据包的接口旁边的捕获 ▶ 选项按钮。这将打开捕获接口对话框。
-
找到你希望使用的接口,并滚动到最右侧列的捕获过滤器选项。
-
你可以通过点击这一列并输入表达式来应用捕获过滤器。我们希望过滤器只显示进出 262 端口的流量,因此输入port 262,如图 4-14 所示。(我们将在下一节详细讨论表达式。)单元格的颜色应该变为绿色,表示你输入了一个有效的表达式;如果表达式无效,单元格会变为红色。
![image]()
图 4-14:在捕获接口对话框中创建捕获过滤器
-
设置好过滤器后,点击开始以开始捕获。
现在,你应该只看到端口 262 的流量,并能够更高效地分析这部分数据。
捕获/BPF 语法
捕获过滤器由 libpcap/WinPcap 应用,并使用伯克利数据包过滤器(BPF)语法。这个语法在多个数据包嗅探应用中常见,主要是因为数据包嗅探应用通常依赖于 libpcap/WinPcap 库,而这些库支持使用 BPF。掌握 BPF 语法对于深入理解网络层级的数据包分析至关重要。
使用 BPF 语法创建的过滤器被称为表达式,每个表达式由一个或多个原语组成。原语由一个或多个限定符(如表 4-2 所列)和一个 ID 名称或编号组成,如图 4-15 所示。
表 4-2: BPF 限定符
| 限定符 | 描述 | 示例 |
|---|---|---|
| 类型 | 标识 ID 名称或编号所代表的内容 | host, net, port |
| 方向 | 指定传输方向到或来自 ID 名称或编号 | src, dst |
| 协议 | 限制匹配特定协议 | ether, ip, tcp, udp, http, ftp |

图 4-15:一个示例捕获过滤器
结合表达式的组成,dst host的限定符与 ID 192.168.0.10 结合形成一个原语。这个原语本身就是一个表达式,它只会捕获目的 IP 地址为 192.168.0.10 的流量。
你可以使用逻辑运算符将原语结合起来,创建更复杂的表达式。共有三种逻辑运算符可用:
• 连接运算符 AND (&&)
• 选择运算符 OR (||)
• 否定运算符 NOT (!)
例如,以下表达式将仅捕获源 IP 地址为 192.168.0.10 且源端口或目标端口为 80 的流量:
src host 192.168.0.10 && port 80
主机名和地址过滤器
你创建的大多数过滤器将集中在特定的网络设备或设备组上。根据具体情况,过滤可以基于设备的 MAC 地址、IPv4 地址、IPv6 地址或 DNS 主机名。
比如,你想了解某个特定主机与网络上服务器交互的流量。你可以在服务器上使用host限定符创建一个过滤器,捕获与该主机 IPv4 地址相关的所有流量:
host 172.16.16.149
如果你在 IPv6 网络中,你可以使用host限定符过滤基于 IPv6 地址的数据,如下所示:
host 2001:db8:85a3::8a2e:370:7334
你还可以通过host限定符基于设备的主机名进行过滤,如下所示:
host testserver2
或者,如果你担心某个主机的 IP 地址可能变化,你也可以通过添加ether协议限定符来基于其 MAC 地址进行过滤:
ether host 00-1a-a0-52-e2-a0
传输方向限定符通常与过滤器一起使用,例如前面示例中的过滤器,用于根据流量是从主机发送还是接收来捕获流量。例如,要仅捕获来自特定主机的流量,可以添加 src 限定符:
src host 172.16.16.149
要仅捕获发送到 172.16.16.149 的数据,可以使用 dst 限定符:
dst host 172.16.16.149
当您不使用类型限定符(host、net 或 port)与原语一起时,默认使用 host 限定符。因此,这个不包含限定符的表达式,相当于之前的示例:
dst 172.16.16.149
端口过滤器
除了根据主机进行过滤外,您还可以根据每个数据包中使用的端口进行过滤。端口过滤可以用于过滤使用已知服务端口的服务和应用程序。例如,以下是一个简单的过滤器,只捕获到或来自端口 8080 的流量:
port 8080
要捕获除端口 8080 以外的所有流量,可以使用以下表达式:
!port 8080
端口过滤器可以与传输方向限定符结合使用。例如,要仅捕获发送到监听标准 HTTP 80 端口的 Web 服务器的流量,可以使用 dst 限定符:
dst port 80
协议过滤器
协议过滤器允许您基于特定协议过滤数据包。它们用于匹配那些不能仅通过使用某个端口来定义的非应用层协议。因此,如果您只想查看 ICMP 流量,可以使用以下过滤器:
icmp
要查看除了 IPv6 流量以外的所有流量,可以使用以下过滤器:
!ip6
协议字段过滤器
BPF 语法的一个真正强大的地方在于,它允许我们检查协议头的每个字节,从而基于这些数据创建非常具体的过滤器。本节中我们将讨论的高级过滤器将允许您从数据包的特定位置开始检索特定数量的字节。
例如,假设我们想根据 ICMP 头部的类型字段进行过滤。类型字段位于数据包的最开始位置,因此它的偏移量是 0。为了标识数据包中需要检查的位置,可以在协议限定符旁边用方括号指定字节偏移量——例如,icmp[0]。这个规范将返回一个 1 字节的整数值,我们可以与之进行比较。例如,为了仅捕获表示目标不可达(类型 3)消息的 ICMP 数据包,我们可以在过滤表达式中使用等于操作符:
icmp[0] == 3
要检查仅表示回显请求(类型 8)或回显回复(类型 0)的 ICMP 数据包,可以使用两个原语与 OR 操作符:
icmp[0] == 8 || icmp[0] == 0
这些过滤器效果很好,但它们仅根据数据包头部中的 1 字节信息进行过滤。您还可以通过在方括号中的偏移量后添加字节长度,并用冒号分隔,来指定过滤表达式中返回的数据长度。
例如,假设我们想要创建一个过滤器,捕获所有 ICMP 目标不可达,主机不可达的数据包,这些数据包的类型是 3,代码是 1。这些是 1 字节的字段,位于数据包头部的偏移量 0 处并紧邻在一起。为此,我们创建一个过滤器,检查数据包头部从偏移量 0 开始的 2 个字节,并将这些数据与十六进制值 0301(类型 3,代码 1)进行比较,如下所示:
icmp[0:2] == 0x0301
一个常见的场景是只捕获 TCP 数据包中 RST 标志位被设置的数据包。我们将在第八章详细讨论 TCP。现在,你只需要知道 TCP 数据包的标志位位于偏移量 13。这是一个有趣的字段,因为它总共占用 1 字节作为标志字段,但每个特定的标志位由这个字节中的单个位标识。正如我将在附录 B 中进一步讨论的那样,每个字节中的位表示某个二进制数。该标志位存储的位由该位表示的数字指定,所以第一个位表示 1,第二个表示 2,第三个表示 4,依此类推。多个标志位可以同时在 TCP 数据包中被设置。因此,我们不能仅使用单一的 tcp[13] 值来进行高效的过滤,因为多个值可能表示 RST 位被设置。
相反,我们必须通过附加一个单一的 & 符号 (&),然后跟上表示该标志存储位置的数字来指定我们希望检查的字节中的位置。RST 标志位位于表示数字 4 的位中,而该位被设置为 4,意味着 RST 标志已被设置。过滤器如下所示:
tcp[13] & 4 == 4
如果想要查看所有设置了 PSH 标志位的数据包,可以使用该标志位在 TCP 标志字段中偏移量 13 的位置,这个位置表示数字 8。我们的过滤器会使用这个位置:
tcp[13] & 8 == 8
示例捕获过滤器表达式
你会经常发现,你的分析成功与否取决于你是否能够为当前情况创建合适的过滤器。表 4-3 展示了一些你可能经常使用的常见捕获过滤器。
表 4-3: 常用的捕获过滤器
| 过滤器 | 描述 |
|---|---|
tcp[13] & 32 == 32 |
TCP 数据包中 URG 标志位被设置 |
tcp[13] & 16 == 16 |
TCP 数据包中 ACK 标志位被设置 |
tcp[13] & 8 == 8 |
TCP 数据包中 PSH 标志位被设置 |
tcp[13] & 4 == 4 |
TCP 数据包中 RST 标志位被设置 |
tcp[13] & 2 == 2 |
TCP 数据包中 SYN 标志位被设置 |
tcp[13] & 1 == 1 |
TCP 数据包中 FIN 标志位被设置 |
tcp[13] == 18 |
TCP SYN-ACK 数据包 |
ether host 00:00:00:00:00:00 |
属于或来自你 MAC 地址的流量 |
!ether host 00:00:00:00:00:00 |
不属于或来自你 MAC 地址的流量 |
broadcast |
仅广播流量 |
icmp |
ICMP 流量 |
icmp[0:2] == 0x0301 |
ICMP 目标不可达,主机不可达 |
ip |
仅 IPv4 流量 |
ip6 |
仅 IPv6 流量 |
udp |
仅 UDP 流量 |
显示过滤器
显示过滤器是指,当应用于捕获文件时,告诉 Wireshark 只显示匹配该过滤器的数据包。你可以在数据包列表窗格上方的过滤器文本框中输入显示过滤器。
显示过滤器比捕获过滤器使用得更频繁,因为它们允许你筛选你看到的数据包,而不会实际删除捕获文件中的其他数据。这样,如果你需要恢复到原始捕获文件,你只需清除过滤器表达式即可。由于 Wireshark 拥有大量的协议分析器,显示过滤器也更为强大。
例如,在某些情况下,你可能会使用显示过滤器从捕获文件中过滤掉无关的广播流量,比如当这些数据包与当前分析的问题无关时,从数据包列表窗格中过滤掉 ARP 广播数据包。然而,由于这些 ARP 广播数据包以后可能会有用,所以最好是临时过滤它们,而不是删除它们。
要在捕获窗口中过滤掉所有 ARP 数据包,将光标置于数据包列表窗格上方的过滤器文本框中,输入 !arp 即可从列表中移除所有 ARP 数据包(见图 4-16)。要移除过滤器,点击X按钮;要保存过滤器以供以后使用,点击加号(+)按钮。

图 4-16:使用位于数据包列表窗格上方的过滤器文本框创建显示过滤器
有两种应用显示过滤器的方法。一种是使用适当的语法直接应用,就像我们在这个例子中做的那样。另一种是使用显示过滤器表达式对话框逐步构建过滤器;当你刚开始使用过滤器时,这种方法更容易。让我们从更简单的方法开始,依次探讨两种方法。
显示过滤器表达式对话框
显示过滤器表达式对话框,如图 4-17 所示,便于新手 Wireshark 用户创建捕获和显示过滤器。要访问此对话框,点击过滤器工具栏上的表达式按钮。

图 4-17:显示过滤器表达式对话框允许在 Wireshark 中轻松创建过滤器。
对话框的左侧列出了所有可能的协议字段,这些字段指定了所有可能的过滤标准。要创建过滤器,请按照以下步骤操作:
-
若要查看与某个协议相关的标准字段,点击该协议旁边的箭头符号展开它。找到你想基于其创建过滤器的标准后,点击选中它。
-
选择你所选字段与所提供的标准值之间的关系。这个关系可以是等于、大于、小于等。
-
通过指定与所选字段相关的标准值来创建你的过滤器表达式。你可以定义此值,或者从 Wireshark 中预定义的选项中选择。
-
你的完整过滤器将在屏幕底部显示。当你完成后,点击 OK 将其插入过滤栏。
显示过滤器表达式对初学者来说很有帮助,但一旦你掌握了操作,你会发现手动输入过滤表达式可以大大提高效率。显示过滤器表达式的语法结构简单而强大。
过滤表达式语法结构
当你开始更多地使用 Wireshark 时,你会希望直接在主窗口中使用显示过滤器语法,以节省时间。幸运的是,显示过滤器使用的语法遵循标准方案,易于导航。在大多数情况下,这个方案是以协议为中心的,遵循协议.特性.子特性`的格式,正如你在查看显示过滤器表达式对话框时看到的。现在我们来看一些例子。
你最常使用捕获或显示过滤器来查看基于特定协议的包。例如,假设你正在排查一个 TCP 问题,并且你只想查看捕获文件中的 TCP 流量。如果是这样,使用简单的 tcp 过滤器就可以完成任务。
现在让我们从另一角度来看问题。假设在排查你的 TCP 问题时,你已经使用了 ping 工具很多次,因此生成了大量的 ICMP 流量。你可以通过过滤器 expression !icmp 从你的捕获文件中去除这些 ICMP 流量。
比较操作符允许你比较值。例如,在排查 TCP/IP 网络问题时,你经常需要查看所有涉及特定 IP 地址的包。等于比较操作符(==)将允许你创建一个过滤器,显示所有 IP 地址为 192.168.0.1 的包:
ip.addr==192.168.0.1
现在假设你只需要查看小于 128 字节的包。你可以使用小于或等于操作符(<=)来实现这个目标:
frame.len<=128
表 4-4 显示了 Wireshark 的比较操作符。
表 4-4: Wireshark 过滤表达式比较操作符
| 操作符 | 描述 |
|---|---|
== |
等于 |
!= |
不等于 |
> |
大于 |
< |
小于 |
>= |
大于或等于 |
<= |
小于或等于 |
逻辑操作符允许你将多个过滤表达式组合成一个语句,从而大大提高过滤器的有效性。例如,假设你只对显示两个 IP 地址的包感兴趣。你可以使用 or 操作符创建一个表达式,显示包含任一 IP 地址的包,如下所示:
ip.addr==192.168.0.1 or ip.addr==192.168.0.2
表 4-5 列出了 Wireshark 的逻辑操作符。
表 4-5: Wireshark 过滤表达式逻辑操作符
| 操作符 | 描述 |
|---|---|
and |
两个条件必须都为真。 |
or |
其中一个条件必须为真。 |
xor |
必须且仅有一个条件为真。 |
not |
两个条件都不为真。 |
示例显示过滤器表达式
尽管创建过滤器表达式的概念相对简单,但在为各种问题创建新过滤器时,你需要使用一些特定的关键词和运算符。表 4-6 展示了我最常用的一些显示过滤器。有关完整的列表,请参考 Wireshark 显示过滤器参考文档,网址为 www.wireshark.org/docs/dfref/。
表 4-6: 常用显示过滤器
| 过滤器 | 描述 |
|---|---|
!tcp.port==3389 |
过滤掉 RDP 流量 |
tcp.flags.syn==1 |
带 SYN 标志的 TCP 数据包 |
tcp.flags.reset==1 |
带 RST 标志的 TCP 数据包 |
!arp |
清除 ARP 流量 |
http |
所有 HTTP 流量 |
tcp.port==23 || tcp.port==21 |
Telnet 或 FTP 流量 |
smtp || pop || imap |
邮件流量(SMTP、POP 或 IMAP) |
保存过滤器
一旦你开始创建大量的捕获和显示过滤器,你会发现自己经常使用某些过滤器。幸运的是,你不需要每次都输入这些过滤器,因为 Wireshark 允许你保存过滤器以便后续使用。要保存自定义捕获过滤器,请按照以下步骤操作:
-
选择 捕获 ▶ 捕获过滤器,以打开捕获过滤器对话框。
-
通过点击对话框左下角的加号(+)按钮来创建一个新过滤器。
-
在“过滤器名称”框中输入过滤器名称。
-
在“过滤器字符串”框中输入实际的过滤器表达式。
-
点击确定按钮,将过滤器表达式保存到列表中。
要保存自定义显示过滤器,请按照以下步骤操作:
-
在主窗口的“数据包列表”面板上方的过滤器栏中输入你的过滤器,并点击栏左侧的按钮。
-
点击保存此过滤器选项,将在单独的对话框中显示已保存的显示过滤器列表。在此,你可以为过滤器提供名称,之后点击确定以保存它(图 4-18)。

图 4-18:你可以直接从主工具栏保存显示过滤器。
将显示过滤器添加到工具栏
如果你发现自己频繁切换的过滤器,一个最简单的操作方式是将过滤器切换按钮添加到数据包列表面板上方的过滤器栏中。为此,完成以下步骤:
-
在主窗口的数据包列表面板上方的过滤器栏中输入过滤器,并点击栏右侧的加号(+)按钮。
-
在过滤器栏下方会显示一个新栏,在该栏中你可以在标签字段中为你的过滤器提供一个名称(图 4-19)。这是将在工具栏上表示该过滤器的标签。一旦你在此字段中输入内容,点击确定即可在过滤器工具栏中创建该表达式的快捷方式。

图 4-19:将过滤器表达式快捷方式添加到过滤器工具栏
如你在图 4-20 中看到的,我们创建了一个快捷方式,可以快速显示所有启用了 RST 标志的 TCP 数据包。对过滤工具栏的添加会保存在你的配置文件中(如第三章中所讨论的),使它们成为增强你在各种场景下识别数据包捕获问题能力的有力工具。

图 4-20:使用工具栏快捷方式进行过滤
Wireshark 包含了几个内置的过滤器,这些过滤器是过滤器应有样子的很好的示例。在创建自己的过滤器时,你会希望使用它们(以及 Wireshark 帮助页面)。在本书的示例中,我们将使用这些过滤器。
第五章:Wireshark 高级功能

一旦掌握了 Wireshark 的基础知识,下一步就是深入了解它的分析和图形化功能。在本章中,我们将探讨一些强大的功能,包括端点和会话窗口、名称解析的细节、协议解析、流量解读、IO 图形分析等。这些功能是 Wireshark 作为图形化分析工具的独特之处,在分析过程中多个阶段都很有用。在继续之前,确保至少尝试使用本章列出的所有功能,因为我们将在书中的后续章节中频繁地回顾这些功能,并探讨实际的分析场景。
端点和网络会话
要进行网络通信,数据必须在至少两个设备之间流动。每个在网络上发送或接收数据的设备都代表了 Wireshark 所称的端点。两个端点之间的通信被称为会话。Wireshark 根据通信的属性,特别是各种协议中使用的地址,描述端点和会话。
端点通过多个地址进行识别,这些地址分配在 OSI 模型的不同层次上。例如,在数据链路层,端点将具有 MAC 地址,这是设备内置的唯一地址(尽管它可以修改,可能使其不再是唯一的)。然而,在网络层,端点将具有 IP 地址,该地址可以随时更改。我们将在接下来的几章中讨论这些地址类型是如何使用的。
图 5-1 展示了两种如何使用地址来识别会话中的端点的示例。图中的会话 A 由在数据链路(MAC)层通信的两个端点组成。端点 A 的 MAC 地址为 00:ff:ac:ce:0b:de,端点 B 的 MAC 地址为 00:ff:ac:e0:dc:0f。会话 B 由两个在网络(IP)层通信的设备定义。端点 A 的 IP 地址为 192.168.1.25,端点 B 的 IP 地址为 192.168.1.30。

图 5-1:网络中的端点和会话
让我们看看 Wireshark 如何提供按端点或会话划分的网络通信信息。
查看端点统计信息
lotsofweb.pcapng
在分析流量时,你可能会发现能够准确定位问题发生在网络的特定端点。例如,打开捕获文件lotsofweb.pcapng,然后打开 Wireshark 的端点窗口(统计 ▶ 端点)。这个窗口展示了每个端点的几个有用统计信息,如图 5-2 所示,包括地址、数据包数量、传输和接收的字节数等。

图 5-2:端点窗口让你查看捕获文件中的每个端点。
窗口顶部的标签(TCP、以太网、IPv4、IPv6 和 UDP)显示按协议组织的端点数量。要仅显示特定协议的端点,点击这些标签中的一个。你可以通过点击屏幕右下角的端点类型框,并选择要添加的协议,来添加额外的协议过滤标签。如果你希望使用名称解析来查看端点地址(请参见第 84 页中的“名称解析”),勾选名称解析复选框。如果你正在处理一个较大的捕获文件并且想要筛选显示的端点,可以在主 Wireshark 窗口中应用显示过滤器,并在端点窗口中选择“限制到显示过滤器”选项。此选项将使窗口仅显示与显示过滤器匹配的端点。
端点窗口的另一个实用功能是可以过滤显示特定的数据包到数据包列表窗格中。这是一种快速深入查看单个端点数据包的方式。右键点击一个端点,选择可用的过滤选项。出现的对话框将允许你显示或排除与选定输入相关的数据包。你还可以在此对话框中选择“着色”选项,将端点地址直接导出为着色规则(着色规则在第四章中有讨论)。通过这种方式,你可以快速突出显示与给定端点相关的数据包,从而在分析时迅速识别它们。
查看网络会话
lotsofweb.pcapng
在 lotsofweb.pcapng 文件仍然打开的状态下,访问 Wireshark 会话窗口 统计 ▶ 会话 (图 5-3) 以显示捕获文件中的所有会话。会话窗口与端点窗口相似,但会话窗口每行显示两个地址,表示一个会话,并且显示每个设备传输的包和字节。列 地址 A 是源端点,地址 B 是目标端点。

图 5-3: 会话窗口让你可以剖析捕获文件中的每个会话。
会话窗口按协议组织。要查看仅使用特定协议的会话,点击窗口顶部的标签(与端点窗口类似),或者点击右下角的会话类型按钮添加其他协议类型。与端点窗口一样,你可以使用名称解析、使用显示过滤器限制可见的会话,或者右键点击特定会话以基于特定会话创建过滤器。基于会话的过滤器对于深入挖掘有趣的通信序列的细节非常有用。
识别顶级会话者与端点和会话
lotsofweb.pcapng
端点和会话窗口在网络故障排除中非常有用,特别是当你试图找到网络中大量流量的源头时。
作为一个例子,我们再看一下 lotsofweb.pcapng。顾名思义,这个捕获文件包含多个客户端浏览互联网时生成的 HTTP 流量。图 5-4 显示了这个捕获文件中的端点列表,按字节数排序。
请注意,负责最多流量(按字节计算)的端点是地址 172.16.16.128。 这是一个内部网络地址(我们将在 第七章 讨论如何确定这一点),作为本次捕获中负责最多通信的设备,它被称为 top talker。

图 5-4:端点窗口显示了哪些主机的通信量最大。
第二高流量的地址是 74.125.103.163,一个外部(互联网)地址。当你遇到一些你不了解的外部地址时,可以搜索 WHOIS 注册表来查找注册的所有者。在这种情况下,来自美国互联网号码注册局(* whois.arin.net/ui/ *)的结果显示,Google 拥有这个 IP 地址,正如 图 5-5 所示。

图 5-5:查看 74.125.103.163 的 WHOIS 结果显示该 IP 属于 Google。
通过 WHOIS 确定 IP 地址所有权
IP 地址的分配由不同的实体根据其地理位置进行管理。ARIN 负责美国及其周边地区的 IP 地址分配,AfriNIC 管理非洲地区的 IP 地址,RIPE 负责欧洲,APNIC 负责亚洲/太平洋地区。通常,你会在负责该 IP 的注册机构的网站上执行 WHOIS 查询。当然,仅通过查看一个地址,你通常无法知道哪个区域注册机构负责它。像 Robtex 这样的站点(* robtex.com/ *)会为你完成这项工作,查询正确的注册机构并提供结果。然而,如果你第一次查询了错误的注册机构,通常会被引导到正确的注册机构。
根据这些信息,你可以假设 172.16.16.128 和 74.125.103.163 要么与多个其他设备进行大量通信,要么它们之间相互通信。实际上,正如大多数顶级通信端点对所示,这两个端点是在互相通信。为了确认这一点,打开“对话”窗口,选择 IPv4 标签,并按字节数对列表进行排序。你应该能看到这两个端点构成了数据传输字节数最多的对话。传输模式表明这是一次大规模的下载,因为来自外部地址 A(74.125.103.163)传输的字节数远大于来自内部地址 B(172.16.16.128)传输的字节数,如图 5-6 所示。

图 5-6:对话窗口确认这两个主要通信端点正在相互通信。
你可以通过应用以下显示过滤器来检查此对话:
ip.addr == 74.125.103.163 && ip.addr == 172.16.16.128
如果你浏览数据包列表,你会看到在数据包列表窗口的“信息”列中有几个针对youtube.com域的 DNS 请求。这与我们发现 74.125.103.163 是谷歌拥有的 IP 地址相符,因为谷歌拥有 YouTube。
你将在本书的剩余章节中看到如何在实际场景中使用端点和对话窗口。
协议层次统计
lotsofweb.pcapng
在处理不熟悉的捕获文件时,有时需要确定流量按协议的分布情况。也就是说,捕获文件中有多少比例是 TCP、IP、DHCP 等协议?与其逐一统计数据包并汇总结果,不如使用 Wireshark 的“协议层次统计”窗口,它可以为你提供这些信息。
例如,保持lotsofweb.pcapng文件打开并清除之前应用的任何过滤器后,选择统计 ▶ 协议层次,如图 5-7 所示,打开“协议层次统计”窗口。

图 5-7:协议层次统计窗口显示流量按协议的分布情况。
协议层次统计窗口为您提供网络上发生的活动类型的快照。在图 5-7 中,100%为以太网流量,99.7%为 IPv4,98%为 TCP,13.5%为来自网页浏览的 HTTP 流量。这些信息为您提供了一个很好的方式来基准测试您的网络,尤其是在您已经对网络流量的常见模式有了直观了解的情况下。例如,如果您知道您的网络流量中通常有 10%是 ARP 流量,但在最近的捕获中看到 50%的 ARP 流量,那么可能有问题。在某些情况下,协议的存在本身就可能引起注意。如果您没有任何设备配置使用生成树协议(STP),那么在协议层次结构中看到它可能意味着某个设备配置错误。
随着时间的推移,您会发现通过查看协议使用情况的分布,您可以仅凭协议层次统计窗口来分析网络中的用户和设备。例如,更高的 HTTP 流量会告诉您有大量的网页浏览活动。您还可能发现,仅凭查看属于某个业务部门的网络段的流量,您就能识别出网络中的特定设备。例如,IT 部门可能使用更多的管理协议,如 ICMP 或 SNMP,客户服务部门可能负责大量的 SMTP(电子邮件)流量,而角落里那个烦人的实习生可能正用魔兽世界流量占满整个网络!
名称解析
网络数据通过各种字母数字地址系统在端点之间传输,这些地址通常过长或过于复杂,不容易记住,例如 MAC 地址 00:16:ce:6e:8b:24,IPv4 地址 192.168.47.122 或 IPv6 地址 2001:db8:a0b:12f0::1。名称解析(也称为名称查找)将一个标识地址转换为另一个地址,主要是为了使地址更容易记住。例如,记住* google.com *比记住 216.58.217.238 要容易得多。通过将易读的名称与这些晦涩的地址关联起来,我们使它们更容易记住和识别。
启用名称解析
Wireshark 可以在显示数据包时使用名称解析来简化分析。要启用 Wireshark 的名称解析,请选择编辑 ▶ 首选项 ▶ 名称解析。该窗口如图 5-8 所示。以下是 Wireshark 中与名称解析相关的主要选项:
解析 MAC 地址 使用 ARP 协议尝试将二层 MAC 地址(例如 00:09:5b:01:02:03)转换为三层地址(例如 10.100.12.1)。如果这些转换失败,Wireshark 会使用程序目录中的ethers文件进行转换尝试。Wireshark 的最后手段是将 MAC 地址的前三个字节转换为设备的 IEEE 指定的制造商名称,例如Netgear_01:02:03。
解析传输名称 尝试将端口号转换为与之相关的名称,例如,将端口 80 显示为 http。当你遇到一个不常见的端口并不知道它通常关联的服务时,这个功能很有用。
解析网络(IP)地址 尝试将第 3 层地址(如 192.168.1.50)转换为易于阅读的 DNS 名称,例如 MarketingPC1.domain.com。这对于识别系统的用途或所有者非常有帮助,前提是该系统有一个描述性的名称。

图 5-8:在首选项对话框中启用名称解析。第一组三个与名称解析类型相关的复选框中,只有“解析 MAC 地址”被选中。
图 5-8 中的名称解析首选项对话框包括一些其他有用的选项:
使用捕获的 DNS 数据包数据进行地址解析 从捕获的 DNS 数据包中解析 DNS 数据,以将 IP 地址解析为 DNS 名称。
使用外部网络名称解析器 允许 Wireshark 向分析机器使用的 DNS 服务器生成查询,以将 IP 地址解析为 DNS 名称。如果您希望使用 DNS 名称解析,但正在分析的捕获数据包中没有相关的 DNS 数据包,这将非常有帮助。
最大并发请求数 限制了可以同时进行的并发 DNS 查询的数量。如果你的捕获操作会生成大量的 DNS 请求,且你担心会占用过多的网络带宽或 DNS 服务器资源,可以使用此选项。
仅使用“hosts”文件配置 限制 DNS 解析仅使用与当前 Wireshark 配置文件关联的主机文件。我将在本节稍后介绍如何使用此文件。
在首选项屏幕中所做的更改将在关闭并重新打开 Wireshark 后保持不变。若要临时更改名称解析设置而不使其保持,您可以通过点击主菜单中的“查看 ▶ 名称解析”来切换名称解析的启用或禁用。您可以选择启用或禁用物理、传输和网络地址的名称解析。
你可以利用各种名称解析工具,使捕获的文件更易于阅读,并在某些情况下节省大量时间。例如,您可以使用 DNS 名称解析帮助快速识别您正在定位的计算机的名称,该计算机是某个特定数据包的来源。
名称解析的潜在缺点
鉴于其优点,使用名称解析可能看起来是显而易见的,但也存在一些潜在的缺点。首先,如果没有 DNS 服务器提供与 IP 地址相关联的名称,网络名称解析可能会失败。名称解析信息不会随捕获文件一起保存,因此每次打开文件时都必须进行解析。如果您在一个网络上捕获数据包,然后在另一个网络上打开该捕获文件,则您的系统可能无法访问源网络的 DNS 服务器,导致名称解析失败。
此外,名称解析需要额外的处理开销。当处理非常大的捕获文件时,您可能希望放弃名称解析,以节省系统资源。如果您尝试打开一个大型捕获文件,发现系统无法加载它,或者 Wireshark 崩溃,禁用名称解析可能会有所帮助。
另一个问题是,网络名称解析依赖于 DNS,这可能会生成不必要的数据包,从而使捕获文件变得混乱,因为流量会发送到 DNS 服务器以解析地址。更复杂的是,如果你分析的捕获文件包含恶意 IP 地址,尝试解析它们可能会生成向攻击者控制的基础设施发送的查询,这可能会让攻击者意识到你已经发现了他们的行动,甚至可能让你成为攻击目标。为了减少污染数据包文件或无意间与攻击者通信的风险,请在“名称解析首选项”对话框中禁用“使用外部网络名称解析器”选项。
使用自定义 hosts 文件
在大型捕获文件中,尤其是当外部主机解析不可用时,跟踪来自多个主机的流量可能会变得繁琐。帮助的方法之一是使用 Wireshark 的hosts文件手动标记系统,文件是一个包含 IP 地址与名称映射的文本文件。你可以使用hosts文件为 Wireshark 中的地址标记名称,以便快速参考。这些名称将显示在数据包列表窗格中。
要使用hosts文件,请按照以下步骤操作:
-
选择编辑 ▶ 首选项 ▶ 名称解析,然后选择仅使用“hosts”配置文件。
-
使用 Windows 记事本或类似的文本编辑器创建一个新文件。文件应包含每行一个条目,其中包括一个 IP 地址和需要解析的名称,如图 5-9 所示。你在右侧选择的名称将在 Wireshark 遇到左侧的 IP 地址时显示在数据包列表窗口中。
![image]()
图 5-9: 创建 Wireshark hosts 文件
-
将文件保存为纯文本文件,并命名为hosts,存储到适当的目录中,如下所示。确保文件没有扩展名!
• Windows:
\Application Data\Wireshark\hosts • OS X: /Users/
/.wireshark/hosts • Linux: /home/
/.wireshark/hosts
现在打开一个捕获文件,你的hosts文件中的任何 IP 地址应该会解析为指定的名称,如图 5-10 所示。取代数据包列表窗口中的源地址和目的地址列显示的 IP 地址,会显示更有意义的名称。

图 5-10:Wireshark 中 hosts 文件的名称解析
以这种方式使用hosts文件可以显著提高你在分析过程中识别特定主机的能力。当与分析团队合作时,考虑在你的网络工作人员之间共享已知资产的hosts文件。这将帮助你的团队快速识别具有静态地址的系统,如服务器和路由器。
注意
如果你的 hosts 文件似乎没有正常工作,请确保你没有不小心为文件名添加文件扩展名。文件名应该只是 hosts。
手动启动名称解析
Wireshark 还具有在临时按需基础上强制进行名称解析的能力。这是通过右键单击数据包列表窗格中的一个数据包,然后选择编辑已解析名称选项来完成的。弹出的窗口允许你为地址指定一个名称,类似于标签。此解析在捕获文件关闭后会丢失,因此这是一种快速标记地址的方法,而无需进行永久性更改,也不必担心以后撤销更改。我经常使用这种技术,因为它比每次查看数据包捕获时手动编辑hosts文件更简单。
协议分解
Wireshark 最大的优势之一是它支持分析超过一千种协议。Wireshark 之所以具有这种能力,是因为它是开源的,从而提供了一个框架来创建协议分解器。这些分解器使 Wireshark 能够识别并解码协议为各种字段,以便在用户界面中显示该协议。Wireshark 使用多个分解器协同工作来解释每个数据包。例如,ICMP 协议分解器使 Wireshark 能够识别 IP 数据包包含 ICMP 数据,提取 ICMP 类型和代码,并将这些字段格式化后显示在数据包列表窗格的“信息”列中。
你可以将分解器看作是原始数据与 Wireshark 程序之间的翻译器。为了让 Wireshark 支持某个协议,该协议必须有一个分解器(或者你可以自己编写一个)。
更改分解器
wrongdissector.pcapng
Wireshark 使用分解器来检测各个协议并决定如何显示网络信息。不幸的是,Wireshark 在选择应用于数据包的分解器时并不总是做出正确的选择。当网络上的协议使用非标准配置时,尤其如此,例如非默认端口(这通常由网络管理员作为安全预防措施配置,或由员工试图规避访问控制时使用)。
当 Wireshark 错误地应用了解析器时,可以覆盖此选择。例如,打开追踪文件wrongdissector.pcapng。该文件包含两台计算机之间的大量 SSL 通信。SSL 是安全套接字层协议,用于主机之间的加密通信。在大多数正常情况下,由于其加密性质,在 Wireshark 中查看 SSL 流量不会获得太多可用信息。然而,这里显然有些问题。如果你通过点击这些数据包并检查数据包字节面板来浏览其中的几个数据包内容,你会发现明文流量。事实上,如果你查看数据包 4,你会发现提到了 FileZilla FTP 服务器应用程序。接下来的几个数据包清楚地显示了用户名和密码的请求和响应。
如果这真的是 SSL 流量,你将无法读取数据包中包含的任何数据,而且你肯定不会看到明文传输的所有用户名和密码,如图 5-11 所示。根据这里显示的信息,可以安全地假设这可能是 FTP 流量,而不是 SSL 流量。Wireshark 可能会将此流量解释为 SSL,因为它使用的是端口 443,如在“信息”列中看到的那样,而端口 443 是 HTTPS(基于 SSL 的 HTTP)的标准端口。

图 5-11:明文用户名和密码?这看起来更像是 FTP 而不是 SSL!
为了修复这个问题,你可以对 Wireshark 应用强制解码,使用 FTP 协议解析器来解析这些数据包。以下是步骤:
-
右键点击协议列中的一个 SSL 数据包(例如数据包 30),然后选择解码为,这将打开一个新对话框。
-
告诉 Wireshark 将所有 TCP 端口 443 流量解码为 FTP,通过选择“字段”列中的 TCP 端口,在“值”列中输入 443,并从“当前”列的下拉菜单中选择 FTP,如图 5-12 所示。
![image]()
图 5-12:解码为...对话框允许你创建强制解码。
-
点击确定,立即将更改应用到捕获文件中。
数据将作为 FTP 流量进行解码,这样你就可以在数据包列表面板中分析它,而无需深入查看单个字节(图 5-13)。

图 5-13:查看正确解码的 FTP 流量
强制解码功能可以在同一个捕获文件中多次使用。Wireshark 会在“解码为...”对话框中跟踪你强制解码的记录,在那里你可以查看和编辑迄今为止创建的所有强制解码。
默认情况下,强制解码不会在你关闭捕获时保存。你可以通过在“解码为...”对话框中点击保存按钮来解决这个问题。这会将协议解码规则保存到你当前的 Wireshark 用户配置文件中;当你使用该配置文件打开任何捕获文件时,这些规则将会被应用。保存的解码规则可以通过点击对话框中的减号按钮来移除。
很容易保存解码规则后就忘记它们。当你没有准备好时,这可能会导致很多困惑,所以要留心强制解码。为了避免自己犯这个疏忽,我通常避免将强制解码保存到我的主 Wireshark 配置文件中。
查看解剖器源代码
使用开源应用程序的好处在于,如果你对某些事情发生的原因感到困惑,你可以查看源代码,找出原因。当你尝试确定某个特定协议为什么被错误解读时,这非常有用,因为你可以检查各个协议解剖器。
通过点击 Wireshark 网站上的“开发”链接并点击“浏览代码”,可以直接查看协议解剖器的源代码。此链接将把你带到 Wireshark 代码仓库,在那里你可以查看最新 Wireshark 版本的发布代码。协议解剖器位于epan/dissectors文件夹中,每个解剖器都标注为packets-
这些文件可能相当复杂,但它们都遵循标准模板,并且通常注释得非常好。你不需要是一个专家级的 C 程序员就能理解每个解剖器的基本功能。如果你想深入理解在 Wireshark 中看到的内容,我建议你查看一些简单协议的解剖器。
跟踪流
http_google.pcapng
Wireshark 最令人满意的分析功能之一是其能够将来自多个数据包的数据重新组合成一个合并的、易于阅读的格式,这通常被称为数据包转录。这样,你就不需要在点击数据包之间时查看客户端到服务器的数据的小块,流跟随功能会将数据排序,便于查看。
有四种类型的流可供跟随:
TCP 流 组装来自使用 TCP 的协议的数据,例如 HTTP 和 FTP。
UDP 流 组装来自使用 UDP 的协议的数据,例如 DNS。
SSL 流 组装来自加密协议的数据,例如 HTTPS。你必须提供密钥来解密流量。
HTTP 流 组装和解压来自 HTTP 协议的数据。当通过 TCP 流跟踪 HTTP 数据时,无法完全解码 HTTP 负载时,这非常有用。
作为一个例子,考虑文件http_google.pcapng中的一个简单 HTTP 事务。点击文件中的任意 TCP 或 HTTP 数据包,右键点击数据包并选择跟踪 TCP 流。这将整合 TCP 流并在一个单独的窗口中打开对话记录,如图 5-14 所示。
此窗口中显示的文本使用了两种颜色,红色文本(在这里用较浅的灰色阴影表示)表示源到目的地的流量,蓝色文本(在这里用较深的灰色阴影表示)则表示目的地到源的流量。颜色的不同与通信的发起方有关。在我们的例子中,客户端发起了与 Web 服务器的连接,因此显示为红色。
TCP 流中的通信以一个初始的GET请求开始,请求访问网站根目录(/),并且服务器以HTTP/1.1 200 OK形式响应,表示请求成功。在数据包捕获中的其他流中也重复出现类似的模式,客户端请求单个文件,服务器相应返回。这实际上是一个用户在浏览 Google 主页的过程,不过您不需要逐个查看每个数据包,而是能够轻松滚动浏览记录。您所看到的是用户所看到的内容,但从内部视角。

图 5-14:跟踪 TCP 流窗口将通信重新组装成易于阅读的格式。
除了在此窗口中查看原始数据外,您还可以在文本中进行搜索;将其保存为文件;打印;或者选择以 ASCII、EBCDIC、十六进制或 C 数组格式查看数据。这些选项位于跟踪流窗口的底部,有助于在处理大量数据时更加便捷。
跟踪 SSL 流
跟踪 TCP 和 UDP 流是一个简单的两步操作,但要以可读格式查看 SSL 流则需要几个额外的步骤。由于流量被加密,您需要提供与负责加密流量的服务器关联的私钥。获取此密钥的方法取决于使用的服务器技术,超出了本书的范围,但一旦您获得了该密钥,您需要按照以下过程将其加载到 Wireshark 中:
-
通过点击编辑 ▶ 首选项来访问 Wireshark 的首选项设置。
-
展开协议部分,点击SSL协议标题(如图 5-15 所示)。点击 RSA 密钥列表标签旁的编辑按钮。
-
点击加号(+)按钮。
-
提供所需的信息。这包括负责加密的服务器的 IP 地址、端口、协议、密钥文件的位置,如果使用了密码,还需提供密钥文件的密码。
-
重启 Wireshark。

图 5-15:添加 SSL 解密信息
一旦此过程完成,你应该能够捕获客户端和服务器之间的加密流量。右键点击一个 HTTPS 数据包,然后点击跟踪 SSL 流以查看明文转录。
查看数据包转录的能力是 Wireshark 中最常用的分析功能之一,你会依赖它来快速确定正在使用哪些特定协议。我们将在后续章节中介绍几个依赖于查看数据包转录的额外场景。
数据包长度
download-slow.pcapng
单个数据包或数据包组的大小可以告诉你很多关于网络状况的信息。在正常情况下,以太网网络中一个帧的最大大小是 1,518 字节。当你从这个数值中减去以太网、IP 和 TCP 头部后,你剩下的是 1,460 字节,这些字节可以用于传输第七层协议头部或数据。如果你知道数据包传输的最小要求,就可以开始查看捕获中数据包长度的分布,以合理推测流量的构成。这对理解大型捕获文件的组成非常有帮助。Wireshark 提供了数据包长度对话框,供你查看根据长度分布的数据包。
让我们通过打开文件download-slow.pcapng来举个例子。打开后,选择统计 ▶ 数据包长度。结果会显示图 5-16 中的数据包长度对话框。

图 5-16:数据包长度对话框帮助你对捕获文件中的流量做出合理的推测。
特别注意显示统计信息的行,其中数据包长度在 1,280 到 2,559 字节之间。像这样的较大数据包通常表示数据传输,而较小的数据包则表示协议控制序列。在这种情况下,我们看到较大数据包的比例很高(66.43%)。即使没有查看文件中的数据包,我们也可以合理推测,捕获文件中包含一个或多个数据传输。这些传输可能是 HTTP 下载、FTP 上传或其他类型的网络通信,其中数据在主机之间传输。
剩余的大多数数据包(33.44%)的长度在 40 到 79 字节之间。这个范围内的数据包通常是 TCP 控制数据包,不携带数据。让我们考虑一下协议头的典型大小。以太网头部是 14 字节(加上 4 字节的 CRC),IP 头部至少是 20 字节,且一个没有数据或选项的 TCP 数据包也是 20 字节。这意味着标准的 TCP 控制数据包——如 SYN、ACK、RST 和 FIN 数据包——大约是 54 字节,符合这个范围。当然,IP 或 TCP 选项的加入会增加这个大小。我们将在第七章和第八章中深入讨论 IP 和 TCP。
检查数据包长度是快速查看大型捕获的好方法。如果有很多大数据包,可以假设正在传输数据。如果大多数数据包较小,说明传输的数据量不多,可以推测捕获的数据主要是协议控制命令。这些并不是硬性规则,但在深入分析之前做出这样的假设会很有帮助。
绘制图表
图表是分析的基础,是获得数据集概览的最佳方式之一。Wireshark 包括了多个图表功能来帮助理解捕获的数据,其中最重要的功能之一就是它的 IO 图表功能。
查看 IO 图表
download-fast.pcapng, download-slow.pcapng, http_espn.pcapng
Wireshark 的 IO 图表窗口允许你绘制网络上数据的吞吐量。你可以使用这些图表来查找数据吞吐量的峰值和低谷,发现单个协议中的性能滞后,或比较同时进行的数据流。
要查看计算机从互联网下载文件时的 IO 图表示例,请打开download-fast.pcapng。点击任何 TCP 数据包以突出显示它,然后选择统计 ▶ IO 图表。
IO 图表窗口显示了数据流随时间变化的图形视图。在图 5-17 的例子中,你可以看到这个图表所代表的下载平均约为每秒 500 个数据包,并且在下载的过程中保持相对一致,直到最后有所下降。

图 5-17:快速下载的 IO 图表大致一致。
让我们将其与一个下载速度较慢的例子进行比较。在保持当前文件打开的情况下,在另一个 Wireshark 实例中打开download-slow.pcapng。调出该下载的 IO 图表,你会看到一个完全不同的情况,如图 5-18 所示。

图 5-18:慢速下载的 IO 图表完全不一致。
这个下载的传输速率介于每秒 0 到 100 个数据包之间,并且其速率远远不一致,有时接近每秒 0 个数据包。如果你将这两个文件的 IO 图表并排放置(见图 5-19),你可以更清楚地看到这些不一致性。在比较两个图表时,请注意 x 轴和 y 轴的数值,以确保你在做公平的比较。图表的比例会根据数据包的数量和/或传输的数据量自动调整,这是图 5-19 中两个图表的一个重要区别。较慢的下载显示的比例在每秒 0 到 100 个数据包之间,而较快的下载比例则在每秒 0 到 700 个数据包之间。

图 5-19:并排查看多个 IO 图表有助于发现变化。
此窗口底部的可配置选项允许你使用多个唯一过滤器(使用与显示或捕获过滤器相同的语法),并为这些过滤器指定显示颜色。例如,你可以为特定 IP 地址创建过滤器,并为其分配独特的颜色,以便查看每个设备的吞吐量差异。我们来试试看。
打开http_espn.pcapng,这是在某设备访问 ESPN 主页时捕获的。如果你查看“会话”窗口,你会看到最活跃的外部 IP 地址是 205.234.218.129\。由此我们可以推断,当访问espn.com时,数据很可能来自于这个主机作为主要内容提供者。然而,还有其他多个 IP 地址参与会话,这很可能是因为额外的内容是从外部内容提供者和广告商处下载的。我们可以使用图 5-20 中的 IO 图来展示直接内容和第三方内容交付之间的差异。

图 5-20:显示两个独立设备 IO 的 IO 图。
该图表中应用的两个过滤器通过 IO 图窗口底部的行表示。名为“Top Talker”的过滤器仅显示 IP 地址 205.234.218.129(我们的主要内容提供者)的 IO 流量。它将以堆叠条形图样式用黑色绘制此值。第二个过滤器,名为“Everything Else”,将显示捕获文件中除了 205.234.218.129 地址之外的所有内容,因此包括所有第三方内容提供者。这一数值将以红色(此处为较浅的灰色)使用堆叠条形图绘制。请注意,我们已经将 y 轴的单位更改为字节/秒。应用这些更改后,轻松看出主要内容提供者和第三方内容提供者之间的差异,并且可以清楚地看到来自第三方源的实际内容量。这是一个有趣的练习,可以在你常访问的网站上重复进行,也是比较不同网络主机 IO 的有用策略。
往返时间图
download-fast.pcapng
Wireshark 的另一个图形功能是能够查看给定捕获文件的往返时间图。往返时间(RTT)是接收到数据包确认所需的时间。实际上,这是数据包到达目标并收到该数据包确认后返回给你的时间。RTT 分析通常用于查找通信中的慢点或瓶颈,并确定是否存在延迟。
让我们试试这个功能。打开文件download-fast.pcapng。通过选择一个 TCP 数据包,然后选择统计 ▶ TCP 流图 ▶ 往返时间图来查看该文件的 RTT 图。download-fast.pcapng的 RTT 图如图 5-21 所示。

图 5-21:快速下载的 RTT 图表看起来大部分保持一致,只有少数偏离值。
图中的每个点表示一个包的 RTT。默认视图将这些值按序列号排序。你可以点击图表中的某个点,直接跳转到“数据包列表”面板中的对应包。
注意
RTT 图是单向的,因此选择正确的流量方向非常重要。如果你的图表看起来不像图 5-21 中的图形,你可能需要点击“切换方向”按钮两次。
看起来快速下载的 RTT 图表大多数 RTT 值都在 0.05 秒以下,只有一些较慢的点位于 0.10 到 0.25 秒之间。尽管有相当多的较高值,但大多数 RTT 值都还可以,因此这将被认为是一个可接受的文件下载 RTT。当检查吞吐量问题的 RTT 图时,应该寻找高延迟时间,这些高延迟时间通过在 y 轴较高位置绘制多个点来表示。
流量图
dns_recursivequery_server.pcapng
流量图功能对于可视化连接和展示随时间变化的数据流非常有用,这些信息使得理解设备之间如何通信变得更加容易。流量图包含一个基于列的连接视图,并组织流量数据,以便可以通过视觉方式进行解读。
要创建流量图,请打开文件 dns_recursivequery_server.pcapng,然后选择 统计信息 ▶ 流量图。生成的图表显示在图 5-22 中。

图 5-22:TCP 流量图让我们能更好地可视化连接。
这个流量图是一个递归 DNS 查询,它是由一个主机接收并转发到另一个主机的 DNS 查询(我们将在第九章中讲解 DNS)。图中的每一条垂直线表示一个独立的主机。流量图是可视化两个设备之间来回通信的好方法,或者像本例中一样,展示多个设备之间的通信关系。它对于理解与不太熟悉的协议的正常通信流动也非常有用。
专家信息
download-slow.pcapng
Wireshark 中每个协议的解析器定义了专家信息,该信息可用于提醒你协议包中的特定状态。这些状态被分为四类。
聊天 基本的通信信息
注意 可能属于正常通信的异常包
警告 可能不属于正常通信的异常包
错误 包中的错误或解析器在解释它时的错误
例如,打开文件 download-slow.pcapng,然后点击 分析 并选择 专家信息,以调出专家信息窗口。在此窗口中,取消选择按总结分组,按严重性整理输出(参见 图 5-23)。

图 5-23:专家信息窗口显示协议解剖器中编程的专家系统信息。
窗口包含针对每种信息分类的部分。此处没有错误,3 条警告,19 条提示信息,和 3 条聊天信息。
该捕获文件中的大部分信息都与 TCP 相关,这是因为专家信息系统传统上主要与该协议配合使用。目前,为 TCP 配置了 29 条专家信息消息,在排查捕获文件时非常有用。当某个数据包满足特定条件时,这些消息将标记该数据包,条件如下所列。(随着我们在 第八章 研究 TCP 和在 第十一章 排查慢速网络时,这些消息的含义将变得更加清晰。)
聊天信息
窗口更新 接收方发送给发送方,通知其 TCP 接收窗口大小已发生变化。
提示信息
TCP 重传 由于数据包丢失导致。当收到重复的 ACK 或数据包的重传计时器到期时,发生重传。
重复的 ACK 当主机未收到期望的下一个序列号时,它会生成一个重复的 ACK,确认最后接收到的数据。
零窗口探测 在发送零窗口数据包后,监控 TCP 接收窗口的状态(详见 第十一章)。
保持连接 ACK 响应保持连接数据包时发送的 ACK。
零窗口探测 ACK 响应零窗口探测数据包时发送的 ACK。
窗口已满 通知发送方接收方的 TCP 接收窗口已满。
警告信息
丢失的前一个段 表示数据包丢失。当数据流中期望的序列号被跳过时发生。
确认丢失的数据包 当看到一个 ACK 数据包,但它所确认的数据包未出现时,发生此情况。
保持连接 当检测到连接保持活动包时触发。
零窗口 当 TCP 接收窗口大小已满并发送零窗口通知,请求发送方停止发送数据时,出现该信息。
乱序 利用序列号检测数据包是否乱序接收。
快速重传 在收到重复的 ACK 后 20 毫秒内发生的重传。
错误信息
没有错误信息
尽管本章讨论的某些特性可能看起来仅在特定情况下使用,但你可能会发现自己比预期更频繁地使用它们。熟悉这些窗口和选项非常重要;在接下来的几章中,我会频繁提到它们。
第六章:命令行上的数据包分析

尽管许多场景可以通过图形用户界面(GUI)解决,但在某些情况下,使用命令行工具——例如 TShark 或 tcpdump——是必要的或更为理想的。以下是一些可能需要使用命令行工具而不是 Wireshark 的情况:
• Wireshark 会一次性提供大量信息。通过使用命令行工具,你可以将显示的信息限制为仅与数据相关的内容,例如只显示包含 IP 地址的单行信息。
• 命令行工具最适合用于过滤数据包捕获文件,并通过 Unix 管道将结果直接提供给其他工具。
• 处理一个非常大的捕获文件时,Wireshark 可能会由于必须将整个文件加载到内存中而感到压力。使用命令行工具对大型捕获文件进行流处理,可以帮助你迅速筛选出相关数据包。
• 如果你正在处理一台服务器且无法访问图形工具,你可能被迫依赖命令行工具。
在本章中,我将演示两种常见的命令行数据包分析工具,TShark 和 tcpdump 的功能。我认为熟悉这两种工具是有帮助的,但通常我在 Windows 系统上使用 TShark,而在 Unix 系统上使用 tcpdump。如果你仅使用 Windows,你可以跳过关于 tcpdump 的部分内容。
安装 TShark
基于终端的 Wireshark,或 TShark,是一个数据包分析应用程序,它提供了与 Wireshark 大致相同的功能,但完全通过命令行接口进行,没有图形用户界面。如果你已经安装了 Wireshark,那么 TShark 也很可能已经安装,除非你在安装 Wireshark 时明确选择不安装它。你可以通过以下步骤来验证 TShark 是否已安装:
-
打开命令提示符。点击 开始菜单,输入 cmd,然后点击 命令提示符。
-
浏览到 Wireshark 安装目录。如果你安装到了默认位置,可以通过在命令提示符中输入 cd C:\Program Files\ Wireshark 进入该目录。
-
运行 TShark 并通过输入 tshark –v 打印其版本信息。如果 TShark 没有安装,你会看到一个错误,提示该命令无法识别。如果 TShark 已安装,你会看到 TShark 版本信息的输出:
C:\Program Files\Wireshark>tshark –v TShark (Wireshark) 2.0.0 (v2.0.0-0-g9a73b82 from master-2.0 --snip--
如果你没有安装 TShark 并且现在希望使用它,可以重新运行 Wireshark 安装程序,并确保选中了 TShark(默认情况下是选中的)。
如果你希望立即开始了解 TShark 的功能,可以通过 –h 参数打印可用的命令。我们将在本章中介绍其中的一些命令。
C:\Program Files\Wireshark>tshark -h
和 Wireshark 一样,TShark 可以运行在多个操作系统上,但由于它不依赖于操作系统特定的图形库,用户体验在不同操作系统平台间更加一致。因此,TShark 在 Windows、Linux 和 OS X 上的操作非常相似。不过,TShark 在每个平台上的运行仍然存在一些差异。本书将重点讲解如何在 Windows 上运行 TShark,因为这是它设计时的主要操作系统。
安装 tcpdump
虽然 Wireshark 是全球最受欢迎的图形化数据包分析应用程序,但 tcpdump 仍然是最受欢迎的命令行数据包分析应用程序。tcpdump 是专为 Unix 类操作系统设计的,通过流行的包管理应用程序很容易安装,并且在许多 Linux 发行版中已经预装。
尽管本书的大部分内容聚焦于 Windows,但也为 Unix 用户包含了 tcpdump 的相关章节。具体来说,我们将使用 Ubuntu 14.04 LTS。如果你想在 Windows 设备上使用 tcpdump,可以下载并安装其 Windows 版本 WinDump,网址是www.winpcap.org/windump/。虽然 tcpdump 和 WinDump 的体验不完全相同,但这两款数据包分析器的功能类似。然而需要注意的是,WinDump 的维护不像 tcpdump 那样活跃。因此,一些较新的功能可能没有,且可能存在安全漏洞。(本书不会涵盖 WinDump。)
Ubuntu 系统没有预装 tcpdump,但由于 APT 包管理系统的存在,安装它非常简单。要安装 tcpdump,请按照以下步骤操作:
-
打开一个终端窗口并执行命令
sudo apt-get update,以确保你的包管理库是最新的,且包含最新的包版本。 -
执行命令
sudo apt-get install tcpdump。 -
系统会提示你安装一些运行 tcpdump 所需的前置条件。当系统提示时,输入 Y 并按
ENTER键允许这些安装。 -
安装完成后,执行命令
tcpdump –h来运行 tcpdump 并打印其版本信息。如果命令执行成功并且终端窗口中出现类似以下文本,你就可以开始使用 tcpdump 了:sanders@ppa:~$ tcpdump -h tcpdump version 4.5.1 libpcap version 1.5.3 Usage: tcpdump [-aAbdDefhHIJKlLnNOpqRStuUvxX#] [ -B size ] [ -c count ] [ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ] [ -j tstamptype ] [ -M secret ] [ -Q metadata-filter-expression ] [ -r file ] [ -s snaplen ] [ -T type ] [ --version ] [ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z command ] [ -Z user ] [ expression ]
你可以通过执行man tcpdump命令来打印 tcpdump 的所有可用命令,如下所示:
sanders@ppa:~$ man tcpdump
我们将讨论如何使用其中的一些命令。
捕获并保存数据包
首要任务是从网络中捕获数据包并将其显示在屏幕上。要在 TShark 中开始捕获,只需执行命令tshark。此命令将启动从网络接口捕获数据包并将其显示在终端窗口的过程,屏幕上会显示类似以下内容:
C:\Program Files\Wireshark>tshark
1 0.000000 172.16.16.128 -> 74.125.95.104 TCP 66 1606 80 [SYN]
Seq=0 Win=8192 Len=0 MSS=1460 WS=4 SACK_PERM=1
2 0.030107 74.125.95.104 -> 172.16.16.128 TCP 66 80 1606 [SYN, ACK]
Seq=0 Ack=1 Win=5720 Len=0 MSS=1406 SACK_PERM=1 WS=64
3 0.030182 172.16.16.128 -> 74.125.95.104 TCP 54 1606 80 [ACK]
Seq=1 Ack=1 Win=16872 Len=0
4 0.030248 172.16.16.128 -> 74.125.95.104 HTTP 681 GET / HTTP/1.1
5 0.079026 74.125.95.104 -> 172.16.16.128 TCP 60 80 1606 [ACK]
Seq=1 Ack=628 Win=6976 Len=0
要在 tcpdump 中开始捕获,执行命令tcpdump。运行此命令后,你的终端窗口应该会显示类似以下内容:
sanders@ppa:~$ tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:18:39.618072 IP 172.16.16.128.slm-api > 74.125.95.104.http: Flags [S],
seq 2082691767, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK],
length 0
21:18:39.648179 IP 74.125.95.104.http > 172.16.16.128.slm-api:
Flags [S.], seq 2775577373, ack 2082691768, win 5720, options [mss
1406,nop,nop,sackOK,nop,wscale 6], length 0
21:18:39.648254 IP 172.16.16.128.slm-api > 74.125.95.104.http: Flags [.],
ack 1, win 4218, length 0
21:18:39.648320 IP 172.16.16.128.slm-api > 74.125.95.104.http: Flags [P.],
seq 1:628, ack 1, win 4218, length 627: HTTP: GET / HTTP/1.1
21:18:39.697098 IP 74.125.95.104.http > 172.16.16.128.slm-api: Flags [.],
ack 628, win 109, length 0
注意
由于在 Unix 系统上捕获数据包需要管理员权限,因此你可能需要以 root 用户身份执行tcpdump,或者在本书中列出的命令前使用sudo命令。在许多情况下,你可能会以具有有限权限的用户身份访问你的 Unix 系统。如果在跟随过程中遇到权限错误,这可能就是原因。
根据你的系统配置,TShark 或 tcpdump 可能不会默认选择你想要捕获流量的网络接口。如果发生这种情况,你需要手动指定它。你可以通过使用–D参数列出 TShark 可用的接口,该命令将以编号列表的形式输出接口,如下所示:
C:\Program Files\Wireshark>tshark -D
1\. \Device\NPF_{1DE095C2-346D-47E6-B855-11917B74603A} (Local Area Connection*
2)
2\. \Device\NPF_{1A494418-97D3-42E8-8C0B-78D79A1F7545} (Ethernet 2)
要使用特定的接口,请使用–i参数,并从接口列表中选择该接口的编号,如下所示:
C:\Program Files\Wireshark>tshark –i 1
该命令将仅从名为“Local Area Connection 2”的接口捕获数据包,该接口在接口列表中的编号为 1。我建议始终指定你要捕获的接口。虚拟机工具或 VPN 常常会添加接口,你要确保你捕获的数据包来自正确的源。
在运行 tcpdump 的 Linux 或 OS X 系统上,使用ifconfig命令列出可用的接口:
sanders@ppa:~$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:1f:a7:55
inet addr:172.16.16.139 Bcast:172.16.16.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe1f:a755/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:5119 errors:0 dropped:0 overruns:0 frame:0
TX packets:3088 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:876746 (876.7 KB) TX bytes:538083 (538.0 KB)
也可以通过使用–i参数来指定接口:
sanders@ppa:~$ tcpdump –i eth0
该命令将专门从 eth0 接口捕获数据包。
一旦你正确配置了所有内容,就可以开始捕获数据包。如果你捕获的设备在网络上即使是稍微繁忙,你可能会注意到,表示单个数据包的行会飞快地出现——可能快得让你根本看不清。我们可以通过将数据包保存到文件中,然后仅从文件中读取其中的一部分来解决这个问题。
在这两个工具中,要将捕获到的数据包保存到文件中,请使用–w参数并指定文件名。捕获将继续运行,直到你通过按下 CTRL-C 停止它。除非另行指定,否则文件将保存到程序执行的目录中。
这是 TShark 中该命令的一个示例:
C:\Program Files\Wireshark>tshark –i 1 –w packets.pcap
该命令将把从接口列表中第一个接口捕获的所有数据包写入packets.pcap。
在 tcpdump 中,相同的命令会是这样的:
sanders@ppa:~$ tcpdump –i eth0 –w packets.pcap
要从保存的文件中读取数据包,请使用–r参数并指定文件名:
C:\Program Files\Wireshark>tshark –r packets.pcap
该命令将把所有数据包从packets.pcap读取到屏幕上。
tcpdump 命令几乎是一样的:
sanders@ppa:~$ tcpdump –r packets.pcap
你可能会注意到,如果你尝试从一个包含大量数据包的文件中读取数据,你会遇到类似前述的情况,数据包会太快滚动,根本来不及阅读。你可以使用–c参数来限制从文件中读取时显示的数据包数量。
例如,以下命令将仅显示 TShark 中捕获文件的前 10 个数据包:
C:\Program Files\Wireshark>tshark –r packets.pcap –c10
在 tcpdump 中,使用相同的参数:
sanders@ppa:~$ tcpdump –r packets.pcap –c10
–c 参数也可以在捕获时使用。执行此命令将仅捕获观察到的前 10 个数据包。将 –c 与 –w 参数结合使用时,也可以将它们保存。
下面是 TShark 中此命令的样子:
C:\Program Files\Wireshark>tshark –i 1 –w packets.pcap –c10
而在 tcpdump 中:
sanders@ppa:~$ tcpdump –i eth0 –w packets.pcap –c10
操作输出
使用命令行工具的一个好处是,输出通常会更为仔细地考虑。图形用户界面(GUI)通常会显示所有内容,用户需要自己去寻找想要的部分。命令行工具通常只显示最基本的信息,迫使用户使用额外的命令来深入挖掘。TShark 和 tcpdump 也不例外。它们每个数据包都显示一行输出,要求用户使用额外的命令查看诸如协议详情或单独字节之类的信息。
在 TShark 输出中,每一行代表一个数据包,行的格式取决于该数据包使用的协议。TShark 使用与 Wireshark 相同的解码器,并以相同的方式分析数据包数据,因此,当 TShark 和 Wireshark 并排运行时,TShark 输出会与 Wireshark 的数据包列表窗格相似。由于 TShark 具有第 7 层协议的解码器,它能够提供比 tcpdump 更多的关于包含头部的数据包的信息。
在 tcpdump 中,每一行也代表一个数据包,格式根据所使用的协议而不同。由于 tcpdump 没有使用 Wireshark 的协议解码器,第 7 层协议的信息不会被工具解析。这是 tcpdump 的最大限制之一。相反,单行数据包会根据其传输层协议格式化,该协议是 TCP 或 UDP(我们将在第八章中了解更多)。
TCP 数据包使用此格式:
[Timestamp] [Layer 3 Protocol] [Source IP].[Source Port] > [Destination IP].
[Destination Port]: [TCP Flags], [TCP Sequence Number], [TCP Acknowledgement
Number], [TCP Windows Size], [Data Length]
UDP 数据包使用此格式:
[Timestamp] [Layer 3 Protocol] [Source IP].[Source Port] > [Destination IP].
[Destination Port]: [Layer 4 Protocol], [Data Length]
这些基本的单行摘要非常适合快速分析,但最终你需要深入分析某个数据包。在 Wireshark 中,你可以通过点击数据包列表窗格中的数据包来实现这一点,从而在数据包详情和数据包字节窗格中显示信息。你也可以通过在命令行中使用一些选项来访问相同的信息。
获取更多关于每个数据包的信息最简单的方法是增加输出的详细程度。
在 TShark 中,使用大写字母 V 来增加详细度:
C:\Program Files\Wireshark>tshark –r packets.pcap –V
这将提供类似 Wireshark 数据包详情窗格的输出,适用于从 packets.pcap 捕获文件读取的数据包。这里展示了一个数据包的正常详细度(基本摘要)和扩展详细度(通过 –V 参数获得的更详细摘要)示例。
首先是标准输出:
C:\Program Files\Wireshark>tshark -r packets.pcap -c1
1 0.000000 172.16.16.172 -> 4.2.2.1 ICMP Echo (ping) request
id=0x0001, seq=17/4352, ttl=128
现在是通过增加详细程度所产生的更深入的信息的一部分:
C:\Program Files\Wireshark>tshark -r packets.pcap -V -c1
Frame 1: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on
interface 0
Interface id: 0 (\Device\NPF_{C30671C1-579D-4F33-9CC0-73EFFFE85A54})
Encapsulation type: Ethernet (1)
Arrival Time: Dec 21, 2015 12:52:43.116551000 Eastern Standard Time
[Time shift for this packet: 0.000000000 seconds]
--snip--
在 tcpdump 中,小写字母 v 用于增加详细程度。与 TShark 不同,tcpdump 允许显示每个数据包的多个详细级别。您可以通过附加额外的 v 来增加最多三层详细度,如下所示:
sanders@ppa:~$ tcpdump –r packets.pcap –vvv
下面展示了同一个数据包在正常详细度和一层扩展详细度下的显示情况。即使在完全详细模式下,这个输出也远不如 TShark 产生的详细。
sanders@ppa:~$ tcpdump -r packets.pcap -c1
reading from file packets.pcap, link-type EN10MB (Ethernet)
13:26:25.265937 IP 172.16.16.139 > a.resolvers.level3.net: ICMP echo request,
id 1759, seq 150, length 64
sanders@ppa:~$ tcpdump -r packets.pcap -c1 -v
reading from file packets.pcap, link-type EN10MB (Ethernet)
13:26:25.265937 IP (tos 0x0, ttl 64, id 37322, offset 0, flags [DF], proto
ICMP (1), length 84)
172.16.16.139 > a.resolvers.level3.net: ICMP echo request, id 1759, seq
150, length 64
可用的详细程度将取决于您正在检查的数据包协议。虽然扩展的详细信息非常有用,但它仍然没有显示我们需要看到的所有内容。TShark 和 tcpdump 会存储每个数据包的全部内容,也可以以十六进制或 ASCII 形式查看。
在 TShark 中,您可以通过使用 –x 参数查看数据包的十六进制和 ASCII 表示,并可以与 r 参数结合使用,从文件中读取并显示数据包:
C:\Program Files\Wireshark>tshark –xr packets.pcap
此视图与 Wireshark 的数据包字节窗格类似,如图 6-1 所示。

图 6-1:在 TShark 中以十六进制和 ASCII 查看原始数据包
在 tcpdump 中,您可以通过使用 –X 开关查看十六进制和 ASCII 表示。您还可以将 –X 与 r 参数结合使用,从数据包文件中读取,如下所示:
sanders@ppa:~$ tcpdump –Xr packets.pcap
这个命令的输出如图 6-2 所示。

图 6-2:在 tcpdump 中以十六进制和 ASCII 查看原始数据包
如果需要,tcpdump 还允许您进行更细粒度的操作。您可以使用 –x(小写字母)参数仅查看十六进制输出,或者使用 –A 参数仅查看 ASCII 输出。
当您开始尝试这些数据输出选项时,很容易被数据淹没。我发现,在命令行分析时,使用最少的信息是最有效的。首先通过默认列表视图查看数据包,当您将分析缩小到几个有趣的数据包时,再使用更详细的输出。这种方法能帮助您避免被大量数据压倒。
名称解析
像 Wireshark 一样,TShark 和 tcpdump 会尝试执行名称解析,将地址和端口号转换为名称。如果您跟随之前的示例,可能已经注意到默认情况下会发生这种情况。如前所述,我通常更倾向于禁用此功能,以防止我的分析在网络中生成更多的数据包。
您可以通过使用 –n 参数在 TShark 中禁用名称解析。这个参数,像许多其他参数一样,可以与其他命令结合使用,以增强可读性:
C:\Program Files\Wireshark>tshark –ni 1
您可以使用 –N 参数启用或禁用某些名称解析方面的功能。如果您使用 –N 参数,所有名称解析将被禁用,除非您明确启用了某些解析。比如,以下命令只会启用传输层(端口名称)解析:
C:\Program Files\Wireshark>tshark –i 1 –Nt
你可以组合多个值。此命令将启用传输层和 MAC 解析:
C:\Program Files\Wireshark>tshark –i 1 -Ntm
使用此选项时,以下值可用:
m MAC 地址解析
n 网络地址解析
t 传输层(端口名)解析
N 使用外部解析器
C 并发 DNS 查找
在 tcpdump 中,使用 –n 将禁用 IP 名称解析,而使用 –nn 则将同时禁用端口名称解析。
此参数也可以与其他命令结合使用,像这样:
sanders@ppa:~$ tcpdump –nni eth1
以下示例展示了先启用端口解析然后禁用端口解析(-n)的捕获数据包。
sanders@ppa:~$ tcpdump -r tcp_ports.pcap -c1
reading from file tcp_ports.pcap, link-type EN10MB (Ethernet)
14:38:34.341715 IP 172.16.16.128.2826 > 212.58.226.142\. ➊http: Flags [S], seq
3691127924, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
sanders@ppa:~$ tcpdump -nr tcp_ports.pcap -c1
reading from file tcp_ports.pcap, link-type EN10MB (Ethernet)
14:38:34.341715 IP 172.16.16.128.2826 > 212.58.226.142\. ➋80: Flags [S], seq
3691127924, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
这两个命令都只读取捕获文件中的第一个数据包 tcp_ports.pcap。第一个命令启用了端口名称解析,并将端口 80 解析为 http ➊,而第二个命令则只显示端口号 ➋。
应用过滤器
在 TShark 和 tcpdump 中,过滤功能非常灵活,因为两者都允许使用 BPF 捕获过滤器。TShark 还可以使用 Wireshark 显示过滤器。就像在 Wireshark 中一样,TShark 中的捕获过滤器只能在捕获时使用,显示过滤器可以在捕获时使用,也可以在显示已捕获的数据包时使用。我们将首先查看 TShark 过滤器。
捕获过滤器可以通过 –f 参数应用,后面跟上你希望使用的 BPF 语法,语法要用引号括起来。此命令只会捕获并保存目标端口为 80 且使用 TCP 协议的数据包:
C:\Program Files\Wireshark>tshark –ni 1 –w packets.pcap –f "tcp port 80"
显示过滤器可以通过 –Y 参数应用,后面跟上你希望使用的 Wireshark 过滤器语法,语法要用引号括起来。可以像这样在捕获时应用:
C:\Program Files\Wireshark>tshark –ni 1 –w packets.pcap –Y "tcp.dstport == 80"
显示过滤器可以在已捕获的数据包上使用相同的参数应用。此命令将仅显示与过滤器匹配的 packets.pcap 文件中的数据包:
C:\Program Files\Wireshark>tshark –r packets.pcap –Y "tcp.dstport == 80"
在 tcpdump 中,你在命令末尾的单引号内指定过滤器。这条命令也将只捕获并保存目标为 TCP 端口 80 的数据包:
sanders@ppa:~$ tcpdump –nni eth0 –w packets.pcap "tcp dst port 80"
你在读取数据包时也可以指定过滤器。此命令将仅显示与过滤器匹配的 packets.pcap 文件中的数据包:
sanders@ppa:~$ tcpdump –r packets.pcap 'tcp dst port 80'
需要记住的是,如果原始捕获文件是在没有过滤器的情况下创建的,那么它仍然包含其他数据包;你只是限制了在从现有文件读取时在屏幕上显示的内容。
如果你有一个包含多种数据包的捕获文件,但你只想过滤出其中的一部分并将该部分保存到一个单独的文件中怎么办?你可以通过结合使用 –w 和 –r 参数来实现:
sanders@ppa:~$ tcpdump –r packets.pcap 'tcp dst port 80' –w http_packets.pcap
这个命令将读取文件packets.pcap,仅筛选出目标为 TCP 端口 80(用于 http)的流量,并将这些数据包写入一个名为http_packets.pcap的新文件。这是一种非常常见的技术,尤其是在您希望保持一个较大的源文件.pcap,但又只想分析其中的一小部分时。我经常使用这种技术通过 tcpdump 将非常大的捕获文件缩小,以便在 Wireshark 中分析数据包的子集。较小的捕获文件更容易处理。
除了指定内联过滤器外,tcpdump 还允许您引用一个包含一系列过滤器的 BPF 文件。当您需要应用一个非常大或复杂的过滤器,且不方便在 tcpdump 命令中进行编辑和维护时,这非常有用。您可以使用–F参数指定一个过滤器文件,如下所示:
sanders@ppa:~$ tcpdump –nni eth0 –F dns_servers.bpf
如果您的文件变得太大,您可能会想添加注释或说明,以便跟踪过滤器每个部分的作用。请记住,BPF 过滤器文件不允许注释,并且如果遇到任何非过滤声明的内容,将会生成错误。由于注释对于解读大型过滤器文件非常有帮助,我通常会保留每个文件的两个副本:一个用于 tcpdump,不包含注释,另一个包含注释供参考。
TShark 中的时间显示格式
一个经常让新分析师困惑的事情是 TShark 的默认时间戳。它显示的是相对于数据包捕获开始的时间戳。在某些情况下,这种时间戳非常有用,但在许多情况下,您可能希望查看数据包实际捕获的时间,就像 tcpdump 时间戳的默认行为一样。您可以通过在 TShark 中使用–t参数,并将值设置为ad(绝对日期)来获得相同的输出:
C:\Program Files\Wireshark>tshark –r packets.pcap –t ad
这是之前相同数据包的比较,显示了默认的相对时间戳➊和绝对时间戳➋:
➊ C:\Program Files\Wireshark>tshark -r packets.pcap -c2
1 0.000000 172.16.16.172 -> 4.2.2.1 ICMP Echo (ping)
request id=0x0001, seq=17/4352, ttl=128
2 0.024500 4.2.2.1 -> 172.16.16.172 ICMP Echo (ping)
reply id=0x0001, seq=17/4352, ttl=54 (request in 1)
➋ C:\Program Files\Wireshark>tshark -r packets.pcap -t ad -c2
1 2015-12-21 12:52:43.116551 172.16.16.172 -> 4.2.2.1 ICMP Echo (ping)
request id=0x0001, seq=17/4352, ttl=128
2 2015-12-21 12:52:43.141051 4.2.2.1 -> 172.16.16.172 ICMP Echo (ping)
reply id=0x0001, seq=17/4352, ttl=54 (request in 1)
通过使用–t参数,您可以指定 Wireshark 中可用的任何时间显示格式。这些格式显示在表 6-1 中。
表 6-1: TShark 中可用的时间显示格式
| 值 | 时间戳 | 示例 |
|---|---|---|
a |
数据包捕获的绝对时间(按您的时区) | 15:47:58.004669 |
ad |
数据包捕获的绝对时间(按您的时区) | 2015-10-09 15:47:58.004669 |
d |
自上一个捕获的数据包以来的时间差(时差) | 0.000140 |
dd |
自上一个显示的数据包以来的时间差 | 0.000140 |
e |
纪元时间(自 1970 年 1 月 1 日以来的秒数,UTC) | 1444420078.004669 |
r |
第一个数据包和当前数据包之间的经过时间 | 0.000140 |
u |
数据包捕获的绝对时间(UTC) | 19:47:58.004669 |
ud |
数据包捕获的绝对时间(UTC 日期) | 2015-10-09 19:47:58.004669 |
不幸的是,tcpdump 没有提供这种级别的控制来操作时间戳的显示方式。
TShark 中的总结统计信息
另一个有用的 TShark 功能(也是它与 tcpdump 的不同之处)是它能够从捕获文件中生成统计信息的子集。这些统计信息与 Wireshark 中的许多功能相似,但提供了方便的命令行访问。统计信息通过使用–z参数并指定你希望生成的输出名称来生成。你可以使用此命令查看所有可用统计信息的完整列表:
C:\Program Files\Wireshark>tshark –z help
我们已经涵盖的许多功能都可以通过–z参数来实现。它们包括使用此命令输出端点和会话统计信息的功能:
C:\Program Files\Wireshark>tshark -r packets.pcap –z conv,ip
此命令将打印packets.pcap文件中关于 IP 会话的统计信息表,如图 6-3 所示。
你还可以使用此参数查看特定协议的信息。如图 6-4 所示,你可以使用http,tree选项以表格形式查看 HTTP 请求和响应的详细信息。
C:\Program Files\Wireshark>tshark -r packets.pcap –z http,tree

图 6-3:使用 TShark 查看会话统计信息

图 6-4:使用 TShark 查看 HTTP 请求和响应的统计信息
另一个有用的功能是查看重组流输出,类似于我们之前通过右键点击 Wireshark 中的数据包并选择“跟随 TCP 流”选项所做的操作。要获取此输出,我们必须使用follow选项,并指定流的类型、输出模式以及我们希望显示的流。你可以通过在输出会话统计信息时,在最左边的列中看到分配给它的编号来识别某个流(如图 6-3 所示)。一个命令可能如下所示:
C:\Program Files\Wireshark>tshark -r http_google.pcap -z follow,tcp,ascii,0
此命令将从http_google.pcap文件中以 ASCII 格式打印 TCP 流 0 的内容。此命令的输出如下所示:
C:\Program Files\Wireshark>tshark -r http_google.pcap -z
--snip--
===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 0
Node 0: 172.16.16.128:1606
Node 1: 74.125.95.104:80
627
GET / HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.7)
Gecko/20091221 Firefox/3.5.7
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PREF=ID=257913a938e6c248:U=267c896b5f39fb0b:FF=4:LD=e
n:NR=10:TM=1260730654:LM=1265479336:GM=1:S=h1UBGonTuWU3D23L;
NID=31=Z-nhwMjUP63e0tYMTp-3T1igMSPnNS1eM1kN1_DUrnO2zW1cPM4JE3AJec9b_
vG-YFibFXszOApfbhBA1BOX4dKx4L8ZDdeiKwqekgP5_kzELtC2mUHx7RHx3PIttcuZ
1406
HTTP/1.1 200 OK
Date: Tue, 09 Feb 2010 01:18:37 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Server: gws
Content-Length: 4633
X-XSS-Protection: 0
你还可以通过提供地址细节来指定你想要查看的流。例如,以下命令将检索指定端点和端口的 UDP 流:
C:\Program Files\Wireshark>tshark –r packets.pcap –z follow,udp,ascii,192.168.
1.5:23429➊,4.2.2.1:53➋
此命令将打印来自packets.pcap的 UDP 流,端点为 192.168.1.5,端口 23429 ➊ 和 4.2.2.1,端口 53 ➋。
这是我最喜欢的一些统计选项:
ip_hosts,tree 显示捕获中的每个 IP 地址,以及每个地址所负责的流量的速率和百分比
io,phs 显示捕获文件中找到的所有协议的协议层次结构
http,tree 显示与 HTTP 请求和响应相关的统计信息
http_req,tree 显示每个 HTTP 请求的统计信息
smb,srt 显示与 SMB 命令相关的统计信息,用于分析 Windows 通信
endpoints,wlan 显示无线端点
expert 显示捕获中的专家信息(聊天、错误等)
使用 –z 参数可以提供许多有用的选项。这里不能一一列出它们,因为需要太多页面,但如果你打算频繁使用 TShark,你应该投入时间查看官方文档,了解更多关于所有可用选项的信息。你可以在这里找到该文档:www.wireshark.org/docs/man-pages/tshark.html。
比较 TShark 和 tcpdump
我们在本章中分析的两个命令行数据包分析应用程序都非常适合各自的任务,使用它们中的任何一个都能以不同的努力程度完成当前任务。有一些差异值得指出,以便你选择最适合的工具:
操作系统 tcpdump 仅适用于基于 Unix 的操作系统,而 TShark 可以在 Windows 和基于 Unix 的系统上运行。
协议支持 这两个工具都支持常见的第 3 层和第 4 层协议,但 tcpdump 对第 7 层协议的支持有限。TShark 提供了丰富的第 7 层协议支持,因为它可以访问 Wireshark 的协议解析器。
分析功能 这两个工具都在很大程度上依赖人工分析来产生有意义的结果,但 TShark 还提供了一套强大的分析和统计功能,类似于 Wireshark,这些功能在没有 GUI 的情况下可以帮助分析。
工具的可用性和个人偏好通常是决定使用哪个应用程序的最终因素。幸运的是,这些工具足够相似,学习其中一个会自然地让你对另一个有所了解,从而使你更加多才多艺,扩大你的工具包。
第七章:网络层协议

无论你是在排查延迟问题、识别故障的应用程序,还是为了发现异常流量而寻找安全威胁,你都必须首先了解正常流量。在接下来的几章中,你将学习正常网络流量如何在数据包层面上工作,我们将从 OSI 模型的底层一路走到顶层。每个协议部分至少有一个相关的抓包文件,你可以直接下载并操作。
在本章中,我们将特别关注网络层协议,这些协议是网络通信的主力军:ARP、IPv4、IPv6、ICMP 和 ICMPv6。
接下来的三章关于网络协议的内容可以说是本书中最重要的章节。跳过这部分讨论就像做感恩节晚餐却没有预热烤箱。即使你已经很好地掌握了每个协议的功能,仍然建议至少快速阅读这些章节,以便复习每个协议的数据包结构。
地址解析协议(ARP)
逻辑地址和物理地址都用于网络中的通信。逻辑地址允许跨多个网络以及间接连接的设备进行通信。物理地址则便于在通过交换机直接连接的设备之间,在同一个网络段内进行通信。在大多数情况下,这两种类型的地址必须协同工作,才能实现通信。
假设你希望与网络上的某个设备进行通信。这个设备可能是某种服务器,或者只是你需要共享文件的另一台工作站。你正在使用的应用程序已经知道远程主机的 IP 地址(通过 DNS,在 第九章中介绍),这意味着系统应该拥有构建它想要传输的数据包的第 3 层到第 7 层信息所需的所有内容。此时唯一需要的信息是包含目标主机 MAC 地址的数据链路层信息。
需要 MAC 地址是因为交换机在网络中连接设备时,使用 内容寻址存储器(CAM)表,该表列出了所有设备在其各个端口上的 MAC 地址。当交换机接收到发送到特定 MAC 地址的流量时,它会使用该表来判断应通过哪个端口转发流量。如果目标 MAC 地址未知,发送设备将首先检查其缓存中是否有该地址;如果没有,则必须通过网络上的额外通信来解析该地址。
TCP/IP 网络(使用 IPv4)将 IP 地址解析为 MAC 地址的过程称为 地址解析协议(ARP),该协议在 RFC 826 中定义。ARP 解析过程仅使用两个数据包:一个 ARP 请求和一个 ARP 响应(见 图 7-1)。
注意
RFC(请求评论)是互联网工程任务组(IETF)和互联网协会(ISOC)发布的技术文献,是定义协议实现标准的机制。你可以在 RFC 编辑器主页上查找 RFC 文档, http://www.rfc-editor.org/。
发送计算机发送出一个 ARP 请求,基本内容是:“大家好,我的 IP 地址是 192.168.0.101,我的 MAC 地址是 f2:f2:f2:f2:f2:f2。我需要将数据发送给拥有 IP 地址 192.168.0.1 的设备,但我不知道其硬件地址。请拥有此 IP 地址的设备回复你的 MAC 地址。”
这个数据包会广播到网络段上的每个设备。任何没有这个 IP 地址的设备都会丢弃这个数据包。拥有该 IP 地址的设备会发送一个 ARP 回复,内容例如:“嘿,发送设备,我就是你在找的,IP 地址是 192.168.0.1,MAC 地址是 02:f2:02:f2:02:f2。”
一旦解析过程完成,发送设备会更新其缓存,记录接收设备的 MAC 与 IP 地址关联关系,并可以开始发送数据。

图 7-1:ARP 解析过程
注意
你可以通过在命令提示符下输入arp –a来查看 Windows 主机的 ARP 表。
看到这个过程的实际操作将帮助你理解它是如何工作的。但在我们查看一些示例之前,先来了解一下 ARP 数据包头部。
ARP 数据包结构
如图 7-2 所示,ARP 头部包括以下字段:
硬件类型 使用的第二层类型——在大多数情况下是以太网(类型 1)
协议类型 ARP 请求所使用的上层协议
硬件地址长度 使用的硬件地址的长度(以八位字节为单位)(以太网为 6)
协议地址长度 指定协议类型的逻辑地址的长度(以八位字节为单位)
操作 ARP 数据包的功能:1 表示请求,2 表示回复

图 7-2:ARP 数据包结构
发送方硬件地址 发送方的硬件地址
发送方协议地址 发送方的上层协议地址
目标硬件地址 目标接收方的硬件地址(ARP 请求中为全零)
目标协议地址 目标接收方的上层协议地址
arp_resolution.pcapng
现在打开文件arp_resolution.pcapng,查看这个解析过程的实际操作。我们将在讲解这个过程时,逐个关注每个数据包。
数据包 1:ARP 请求
第一个数据包是 ARP 请求,如图 7-3 所示。我们可以通过检查 Wireshark 的“数据包详情”窗格中的以太网头部来确认该数据包是一个真正的广播数据包。该数据包的目的地址是 ff:ff:ff:ff:ff:ff ➊。这是以太网广播地址,发送到该地址的任何数据包都会被广播到当前网络段上的所有设备。数据包在以太网头部中的源地址列出了我们的 MAC 地址 ➋。
基于这个结构,我们可以判断这确实是一个在以太网网络上使用 IPv4 的 ARP 请求。发送者的 IP 地址(192.168.0.114)和 MAC 地址(00:16:ce:6e:8b:24)已列出 ➌,目标的 IP 地址(192.168.0.1)也列出 ➎。目标的 MAC 地址——我们试图获取的信息——未知,因此目标 MAC 列出了 00:00:00:00:00:00 ➍。

图 7-3:ARP 请求数据包
数据包 2:ARP 应答
在对初始请求的应答中(见图 7-4),以太网头部的目的地址现在是第一个数据包中的源 MAC 地址。ARP 头部与 ARP 请求的相似,只是有一些变化:
• 该数据包的操作码(opcode)现在是 0x0002 ➊,表示这是一个应答而不是请求。
• 地址信息被反转——发送者的 MAC 地址和 IP 地址现在成为目标 MAC 地址和 IP 地址 ➌。
• 最重要的是,所有信息都已呈现,这意味着我们现在得到了我们的主机在 192.168.0.1 上的 MAC 地址(00:13:46:0b:22:ba) ➋。

图 7-4:ARP 应答数据包
无偿 ARP
arp_gratuitous.pcapng
在我所在的地方,当某事是“无偿”做的时,这个词通常带有负面含义。然而,无偿的 ARP却是一件好事。
在许多情况下,设备的 IP 地址可能会发生变化。当这种情况发生时,网络中主机的 IP 到 MAC 地址映射会变得无效。为了防止这导致通信错误,一个无偿的 ARP 数据包会在网络上发送,强制任何接收到该数据包的设备更新其缓存中的 IP 到 MAC 地址映射(见图 7-5)。

图 7-5:无偿 ARP 过程
有几种不同的场景可能会生成无偿的 ARP 数据包。最常见的一种情况是 IP 地址的变化。打开捕获文件arp_gratuitous.pcapng,你会看到这个过程的实际情况。这个文件仅包含一个数据包(见图 7-6),因为无偿的 ARP 只涉及一个数据包。

图 7-6:一个无偿 ARP 数据包
检查以太网头部,你可以看到这个数据包作为广播发送,这样网络上的所有主机都能接收到它 ➊。ARP 头部看起来像是一个 ARP 请求,不同之处在于发送方的 IP 地址 ➋ 和目标 IP 地址 ➌ 是相同的。当网络中的其他主机接收到这个数据包时,它会导致它们更新 ARP 表,将新的 IP 到 MAC 地址的映射加入其中。由于这个 ARP 数据包是无请求的,但却导致客户端更新其 ARP 缓存,因此该数据包被视为不必要的。
你会在一些情况下注意到不必要的 ARP 数据包。如前所述,改变设备的 IP 地址会生成一个不必要的数据包。此外,一些操作系统在启动时会执行不必要的 ARP 请求。此外,一些系统使用不必要的 ARP 数据包来支持负载均衡。
互联网协议(IP)
OSI 模型第 3 层的协议主要目的是允许不同网络之间的通信。正如你刚才看到的,MAC 地址用于第 2 层单一网络上的通信。类似地,第 3 层负责处理用于不同网络间通信的地址。有一些协议可以实现这一点,但最常见的是互联网协议(IP),目前有两个版本在使用——IP 版本 4 和 IP 版本 6。我们将从 RFC 791 中定义的 IP 版本 4(IPv4)开始。
互联网协议版本 4 (IPv4)
要理解 IPv4 的功能,你需要知道网络间流量是如何流动的。IPv4 是通信过程中的主力军,最终负责在设备之间传递数据,无论通信端点位于何处。
所有设备通过集线器或交换机连接的简单网络称为 局域网(LAN)。当你想要连接两个局域网时,可以通过路由器来实现。复杂的网络可以由成千上万的局域网通过成千上万的路由器连接在全球范围内组成。互联网本身就是由数百万个局域网和路由器组成的。
IPv4 地址
IPv4 地址是 32 位分配的数字,用于唯一标识连接到网络的设备。要记住一个由 32 个字符长的零和一组成的序列是相当困难的,因此 IP 地址采用 点分四段(或 点分十进制)表示法来书写。
在点分四段表示法中,构成 IP 地址的四组零和一被转换为十进制,并表示为 0 到 255 之间的数字,格式为 A.B.C.D(见 图 7-7)。例如,考虑 IP 地址 11000000 10101000 00000000 00000001。这个值显然是难以记住或标注的。幸运的是,使用点分四段表示法,我们可以将其表示为 192.168.0.1。

图 7-7:点分四段 IPv4 地址表示法
一个 IP 地址由两部分组成:网络部分和主机部分。网络部分标识设备连接的局域网,而主机部分标识该网络中的设备。确定 IP 地址的哪一部分属于网络部分或主机部分并不总是相同的。这些信息通过另一组地址信息传达,这组信息称为网络掩码(netmask),有时也叫做子网掩码。
注意
在本书中,当我们提到 IP 地址时,我们总是指 IPv4 地址。稍后在本章中,我们将讨论使用不同地址规则的 IP 版本 6。每当我们提到 IPv6 地址时,都会明确标注。
网络掩码标识了 IP 地址中哪一部分属于网络部分,哪一部分属于主机部分。网络掩码的长度也是 32 位,每个位为 1 的部分标识 IP 地址中保留给网络部分的部分。其余的位被设置为 0,以标识主机部分。
例如,考虑 IP 地址 10.10.1.22,二进制表示为 00001010 00001010 00000001 00010110。为了确定 IP 地址各部分的分配方式,我们可以应用我们的网络掩码。在这种情况下,我们的网络掩码是 11111111 11111111 00000000 00000000。这意味着 IP 地址的前半部分(10.10 或 00001010 00001010)保留给网络部分,而 IP 地址的后半部分(.1.22 或 00000001 00010110)标识此网络中的单个主机,如图 7-8 所示。

图 7-8:子网掩码决定了 IP 地址中各位的分配方式。
如图 7-8 所示,网络掩码也可以用点分十进制表示法表示。例如,网络掩码 11111111 11111111 00000000 00000000 表示为 255.255.0.0。
IP 地址和网络掩码通常采用无类域间路由(CIDR)表示法书写。在这种形式下,IP 地址写出完整,然后是一个斜杠(/)和表示 IP 地址网络部分的位数。例如,IP 地址 10.10.1.22 和网络掩码 255.255.0.0 会写成 CIDR 表示法为 10.10.1.22/16。
IPv4 数据包结构
源 IP 地址和目的 IP 地址是 IPv4 数据包头部的关键组成部分,但这并不是数据包中包含的所有 IP 信息。与我们刚刚检查过的 ARP 数据包相比,IP 头部要复杂得多;它包括许多额外的功能,帮助 IP 完成其任务。
如图 7-9 所示,IPv4 头部包含以下字段:
版本 正在使用的 IP 版本(IPv4 时始终为 4)。头部长度 IP 头部的长度。
服务类型 优先级标志和服务类型标志,路由器用来优先处理流量。
总长度(Total Length) IP 头部和数据包中包含的数据的长度。
标识符(Identification) 用于标识数据包或碎片化数据包序列的唯一标识号码。
标志(Flags) 用于标识数据包是否是碎片化数据包序列的一部分。
碎片偏移量(Fragment Offset) 如果数据包是碎片,使用此字段的值来按正确顺序重新组装数据包。
生存时间(Time to Live) 定义数据包的生命周期,以跳数或通过路由器的秒数来衡量。
协议(Protocol) 标识封装 IPv4 头部的传输层头部。
头部校验和(Header Checksum) 用于错误检测的机制,用以验证 IP 头部的内容是否损坏或受损。
源 IP 地址(Source IP Address) 发送数据包的主机的 IP 地址。
目的地 IP 地址(Destination IP Address) 数据包目的地的 IP 地址。
选项(Options) 预留用于额外的 IP 选项。包括源路由和时间戳选项。
数据(Data) 实际上传输的 IP 数据。

图 7-9:IPv4 数据包结构
生存时间(Time to Live)
ip_ttl_source.pcapng ip_ttl_dest.pcapng
生存时间(TTL) 值定义了数据包可以经过的最大时间或最大路由器数量,超过此时间或数量后数据包会被丢弃(适用于 IPv4)。TTL 在数据包创建时被定义,通常每次数据包被路由器转发时,TTL 值会减 1。例如,如果数据包的 TTL 为 2,第一个到达的路由器会将 TTL 减为 1,并将数据包转发到第二个路由器。第二个路由器会再将 TTL 减为 0,如果数据包的最终目的地不在该网络上,数据包将被丢弃(见 图 7-10)。

图 7-10:数据包的 TTL 每次经过路由器时都会减少。
为什么 TTL 值很重要?通常,我们只关心数据包从源地址到目的地所需的时间。然而,考虑到一个数据包必须通过多个路由器传输到互联网上的主机。在该数据包的路径中,可能会遇到配置错误的路由器,并失去到达最终目的地的路径。在这种情况下,路由器可以执行多种操作,其中一种可能导致数据包在网络中永无止境地循环。
无限循环可能会引发各种问题,但通常会导致程序或整个操作系统崩溃。从理论上讲,网络中的数据包也可能发生类似情况。数据包将不断地在路由器之间循环。随着循环数据包的数量增加,网络中的带宽将被耗尽,直到发生拒绝服务的情况。为防止这种情况发生,TTL 被创建。
让我们在 Wireshark 中看一个示例。文件ip_ttl_source.pcapng包含两个 ICMP 数据包。ICMP(在本章稍后讨论)使用 IP 来传输数据包,我们可以通过展开“数据包详情”窗格中的 IP 头部部分来查看这一点(见图 7-11)。

图 7-11:源数据包的 IP 头部
你可以看到使用的 IP 版本是版本 4 ➊,IP 头长度是 20 字节 ➋,头部和负载的总长度是 60 字节 ➌,TTL 字段的值是 128 ➍。
ICMP Ping 的主要目的是测试设备间的通信。数据从一个主机发送到另一个主机作为请求,接收主机应该将数据作为回复发回。在这个文件中,我们有一个地址为 10.10.0.3 ➎的设备向一个地址为 192.168.0.128 ➏的设备发送 ICMP 请求。这个初始的捕获文件是在源主机 10.10.0.3 处创建的。
现在打开文件ip_ttl_dest.pcapng。在这个文件中,数据是在目标主机 192.168.0.128 处捕获的。展开这个捕获中第一个数据包的 IP 头部以检查其 TTL 值(见图 7-12)。
你应该立刻注意到 TTL 值为 127 ➊,比原始 TTL 值 128 少了 1。即使不了解网络的架构,我们也可以得出结论:有一台路由器将这些设备隔开,因此通过该路由器的传输将 TTL 值减少了 1。

图 7-12:IP 头部显示 TTL 已经减少了 1。
IP 分片
ip_frag_source.pcapng
数据包分片是 IP 的一个特性,它通过将数据流分割成更小的片段,从而允许在不同类型的网络中可靠地传输数据。
数据包的分片是基于使用的第 2 层数据链路协议的最大传输单元(MTU)大小以及使用该第 2 层协议的设备配置。在大多数情况下,使用的第 2 层数据链路协议是以太网。以太网的默认 MTU 为 1,500 字节,这意味着可以通过以太网网络传输的最大数据包大小为 1,500 字节(不包括 14 字节的以太网头部)。
注意
尽管有标准的 MTU 设置,但在大多数情况下,设备的 MTU 可以手动重新配置。MTU 设置是按每个接口分配的,并且可以在 Windows 和 Linux 系统上修改,也可以在管理型路由器的接口上进行修改。
当设备准备发送 IP 数据包时,它会通过将数据包的大小与将要传输该数据包的网络接口的 MTU 进行比较,来决定是否需要分片。如果数据包的大小大于 MTU,则该数据包将被分片。分片数据包的步骤如下:
-
设备将数据分割成成功传输所需的数据包数量。
-
每个 IP 头的总长度字段设置为每个碎片的段大小。
-
数据流中的所有数据包,除了最后一个,都设置了更多碎片标志为 1。
-
碎片偏移字段被设置在碎片的 IP 头中。
-
数据包被传输。
文件ip_frag_source.pcapng是从地址为 10.10.0.3 的计算机上获取的,该计算机向地址为 192.168.0.128 的设备发送了 ping 请求。注意,在数据包列表窗格中的信息列列出了两个碎片化的 IP 数据包,后面是 ICMP(ping)请求。
从检查数据包 1 的 IP 头开始(见图 7-13)。

图 7-13:更多碎片标志和碎片偏移值可以指示一个碎片化的数据包。
你可以根据更多碎片标志和碎片偏移字段看出该数据包是一个碎片。碎片数据包要么具有正的碎片偏移值,要么设置了更多碎片标志。在第一个数据包中,设置了更多碎片标志➊,表示接收设备应该期待接收到此序列中的另一个数据包。碎片偏移设置为 0➋,表示该数据包是碎片序列中的第一个。
第二个数据包的 IP 头(见图 7-14)也设置了更多碎片标志➊,但在这种情况下,碎片偏移值为 1480➋。这表明 MTU 为 1,500 字节,减去 20 字节的 IP 头。
第三个数据包(见图 7-15)没有设置更多碎片标志➋,这标志着它是数据流中的最后一个碎片,碎片偏移值设置为 2960➌,这是 1480 + (1500 – 20)的结果。由于它们在 IP 头的标识符字段中有相同的值➊,因此这些碎片可以被识别为同一数据系列的一部分。

图 7-14:碎片偏移值会根据数据包的大小增加。

图 7-15:更多碎片标志未设置,表示该碎片是最后一个。
尽管在网络中看到碎片化的数据包不像过去那么常见,但理解为什么数据包会被碎片化是很有用的,这样当你遇到它们时,便能诊断问题或发现丢失的碎片。
互联网协议第六版(IPv6)
当编写 IPv4 规范时,没人预料到我们最终会拥有今天那么多的互联网连接设备。IPv4 最大可寻址空间仅限于大约 43 亿个地址。实际的可寻址空间在减去保留给特殊用途的地址范围(如测试、广播流量和 RFC1918 内部地址)后,进一步缩小。尽管进行了多次努力以延缓 IPv4 地址的枯竭,但最终解决这一限制的唯一方法是开发新的 IP 规范版本。
因此,IPv6 规范应运而生,第一版于 1998 年发布,作为 RFC 2460。这一版本提供了几项性能提升,包括更大的地址空间。在本节中,我们将研究 IPv6 数据包的结构,并讨论 IPv6 通信与其前身的区别。
IPv6 地址
IPv4 地址的位数限制为 32 位,提供了一个以十亿为单位的可寻址空间。IPv6 地址为 128 位,提供了一个以不可计数大数(万亿万亿万亿)为单位的可寻址空间。这可真是一次大升级!
由于 IPv6 地址为 128 位,因此以二进制形式管理它们比较笨重。大多数情况下,IPv6 地址以八组 2 字节的十六进制表示,每组之间用冒号分隔。例如,一个非常简单的 IPv6 地址看起来是这样的:
1111:aaaa:2222:bbbb:3333:cccc:4444:dddd
你的第一个想法可能和许多习惯记住 IPv4 地址的人一样:IPv6 地址几乎不可能记住。这是一个为了更大的地址空间所作的无奈取舍。
IPv6 地址表示法的一个特点是在某些情况下可以折叠零组。例如,考虑以下 IPv6 地址:
1111:0000:2222:0000:3333:4444:5555:6666
你可以将包含零的分组完全折叠,以使其不可见,如下所示:
1111::2222:0000:3333:4444:5555:6666
然而,你只能折叠单一的一组零,因此以下地址将是无效的:
1111::2222::3333:4444:5555:6666
另一个需要考虑的问题是 IPv6 地址中的前导零可以被省略。考虑以下示例,其中第四、第五和第六组前面有零:
1111:0000:2222:0333:0044:0005:ffff:ffff
你可以像这样更高效地表示地址:
1111::2222:333:44:5:ffff:ffff
这不像 IPv4 地址那样容易使用,但比起更长的表示法,处理起来要容易得多。
IPv6 地址包含网络部分和主机部分,通常分别称为 网络前缀 和 接口标识符。这些字段的分配方式取决于 IPv6 通信的分类。IPv6 流量被分为三种分类:单播、多播或任播。在大多数情况下,你可能会处理链路本地单播流量,即在网络内部一个设备与另一个设备之间的通信。链路本地单播 IPv6 地址的格式如 图 7-16 所示。

图 7-16:IPv6 链路本地单播地址的各个部分
链路本地地址用于当通信目标是同一网络内的另一台设备时。链路本地地址的标识方法是其最重要的 10 位设置为 1111111010,接下来的 54 位全部为零。因此,当地址的前半部分为 fe80:0000:0000:0000 时,你可以辨认出这是一个链路本地地址。
链路本地 IPv6 地址的后半部分是接口 ID 部分,它唯一标识端点主机上的网络接口。在以太网网络中,这可以基于接口的 MAC 地址。然而,MAC 地址只有 48 位。为了填满整个 64 位空间,MAC 地址被分成两半,并在每一半之间添加值 0xfffe 作为填充,以创建唯一标识符。最后,第一个字节的第七位被反转。这有点复杂,但可以参考图 7-17 中的接口 ID。表示此 ID 的设备的原始 MAC 地址是 78:31:c1:cb:b2:56。字节 0xfffe 被添加在中间,反转第一个字节的第七位将8变为a。

图 7-17:接口 ID 使用接口的 MAC 地址和填充。
IPv6 地址可以像 IPv4 地址一样使用 CIDR 表示法表示。在这个例子中,64 位的可寻址空间使用链路本地地址表示:
fe80:0000:0000:0000:/64
当 IPv6 地址用于通过公共互联网路由的全局单播流量时,其组成会发生变化(见图 7-18)。以这种方式使用时,全局单播的特点是其前 3 个位设置为 001,后跟一个 45 位的全局路由前缀。全局路由前缀由互联网号码分配局(IANA)分配给组织,用于唯一标识一个组织的 IP 空间。接下来的 16 位是子网 ID,可用于分层地址分配,类似于 IPv4 地址的网络掩码部分。最后的 64 位用于接口 ID,和链路本地单播地址一样。路由前缀和子网 ID 的大小可以有所不同。

图 7-18:IPv6 全局单播地址的各部分
相较于 IPv4,IPv6 在路由数据包到达目的地和有效利用地址空间方面提供了更高的效率。这种效率得益于更大的地址范围,以及链路本地和全局地址的使用,结合唯一的主机标识符。
注意
你可以很容易地视觉区分 IPv6 和 IPv4 地址,但许多程序不能这样做。如果你需要指定 IPv6 地址,一些应用程序,如浏览器或命令行工具,要求你将地址放在方括号内,例如:[1111::2222:333:44:5:ffff]。这个要求并不总是有很好的文档说明,许多人在学习 IPv6 时因此感到沮丧。
IPv6 数据包结构
http_ip4and6.pcapng
IPv6 头部的结构已经扩展,以支持更多功能,但它也被设计得更易解析。头部现在是固定的 40 字节,而不是具有需要检查的头部长度字段的可变大小。附加选项通过扩展头部提供。其好处是,大多数路由器只需要处理 40 字节的头部即可转发数据包。
如 图 7-19 所示,IPv6 头部包含以下字段:
版本 正在使用的 IP 版本(对于 IPv6,总是为 6)。
流量类别 用于对某些类别的流量进行优先级排序。

图 7-19:IPv6 数据包结构
流标签 由源使用来标记属于同一流的一组数据包。此字段通常用于服务质量(QoS)管理,并确保属于同一流的数据包走相同的路径。
有效载荷长度 紧随 IPv6 头部后的数据载荷的长度。
下一个头部 标识封装 IPv6 头部的第 4 层头部。此字段替代了 IPv4 中的协议字段。
跳数限制 定义数据包的生命周期,以通过路由器的跳数来衡量。此字段替代了 IPv4 中的 TTL 字段。
源 IP 地址 发送数据包的主机的 IP 地址。
目的地 IP 地址 数据包目的地的 IP 地址。
我们通过比较 IPv4 和 IPv6 数据包,查看一些差异,参见 http_ip4and6.pcapng。在此抓包中,配置了一个 Web 服务器,监听同一物理主机上的 IPv4 和 IPv6 连接。一个配置了 IPv4 和 IPv6 地址的客户端独立地使用各自的地址浏览服务器,并通过 curl 应用程序使用 HTTP 下载 index.php 页面(见 图 7-20)。
打开抓包文件后,你应该能够根据数据包列表区域中的源和目的地列地址,轻松看到哪些数据包属于哪个会话。数据包 1 到 10 表示 IPv4 流(流 0),数据包 11 到 20 表示 IPv6 流(流 1)。你可以从会话窗口过滤每个流,或在过滤栏中输入 tcp.stream == 0 或 tcp.stream == 1。

图 7-20:使用不同 IP 版本的相同物理主机之间的连接
我们将在 第八章 中深入讨论 HTTP,这是负责提供网页的协议。在这个例子中,只需注意,无论使用哪种下层网络协议,提供网页的业务始终保持一致。TCP 也是如此,它的操作方式也始终一致。这是封装作用的一个典型例子。尽管 IPv4 和 IPv6 的工作方式不同,但不同层次的协议并不受影响。
图 7-21 提供了两个数据包的并排比较,功能相同——数据包 1 和数据包 11。两个数据包都是 TCP SYN 数据包,旨在从客户端发起与服务器的连接。这些数据包的以太网和 TCP 部分几乎相同。然而,IP 部分完全不同。
• 源地址和目标地址格式不同 ➏➓。
• IPv4 数据包为 74 字节,总长度为 60 字节 ➊,其中包括 IPv4 头和有效载荷,以及 14 字节的以太网头。IPv6 数据包为 96 字节,其中包括 40 字节的 IPv6 有效载荷 ➐,并且有一个独立的 40 字节 IPv6 头和 14 字节的以太网头。IPv6 头是 40 字节,是 IPv4 头 20 字节的两倍,以适应更大的地址大小。
• IPv4 通过协议字段 ➍识别协议,而 IPv6 通过下一个头字段(也可以用于指定扩展头) ➑识别协议。
• IPv4 有 TTL 字段 ➌,而 IPv6 使用跳数限制字段 ➒来实现相同的功能。
• IPv4 包含一个头部校验和值 ➎,而 IPv6 则没有。
• IPv4 数据包没有被分片,但它仍包括这些选项的值 ➋。IPv6 头部不包含这些信息,因为如果需要分片,它将在扩展头中实现。

图 7-21:IPv4(上)和 IPv6(下)数据包并排比较,执行相同功能
并排比较 IPv4 和 IPv6 流量是完全理解这两种协议如何操作差异的好方法。
邻居请求与 ARP
icmpv6_neighbor_solicitation.pcapng
当我们之前讨论不同的流量分类时,我列出了单播、多播和任播,但没有列出广播流量。IPv6 不支持广播流量,因为广播被视为一种低效的传输机制。由于没有广播,ARP 无法用于主机之间在网络上的相互发现。那么,IPv6 设备是如何找到彼此的呢?
答案在于一个名为邻居请求的新特性,这是邻居发现协议(NDP)的一部分,它利用 ICMPv6(在本章最后一节讨论)来完成这项工作。为了实现这个任务,ICMPv6 使用多播,一种通信方式,只有订阅特定数据流的主机才能接收并处理它。多播流量可以迅速识别,因为它有自己保留的 IP 空间(ff00::/8)。
尽管地址解析过程依赖于不同的协议,但它仍然使用非常简单的请求/响应工作流。例如,假设一个 IPv6 地址为 2001:db8:1:2::1003 的主机想与另一个地址为 2001:db8:1:2::1000 的主机通信。就像 IPv4 一样,源设备必须能够确定它想要通信的主机的链路层(MAC)地址,因为这是网络内部通信。该过程如 图 7-22 所示。

图 7-22:地址解析的邻居请求过程
在此过程中,主机 2001:db8:1:2::1003 通过多播向网络上的每个设备发送一个邻居请求(ICMPv6 类型 135)包,询问:“IP 地址为 2001:db8:1:2::1000 的设备的 MAC 地址是什么?我的 MAC 地址是 00:0C:29:2f:80:31。”
被分配了该 IPv6 地址的设备将接收到此多播传输,并通过邻居广告(ICMPv6 类型 136)包响应源主机。此包内容为:“你好,我的网络地址是 2001:db8:1:2::1000,我的 MAC 地址是 00:0c:29:1f:a7:55。”收到此消息后,通信可以开始。
你可以在捕获文件 icmpv6_neighbor_solicitation.pcapng 中看到此过程的实际操作。该捕获文件展示了我们刚才讨论的示例,其中 2001:db8:1:2::1003 想与 2001:db8:1:2::1000 通信。查看第一个包并展开“包详细信息”窗口中的 ICMPv6 部分(图 7-23),可以看到该包是 ICMP 类型 135 ➋,从 2001:db8:1:2::1003 发送到多播地址 ff02::1:ff00:1000 ➊。源主机提供了它想要通信的目标 IPv6 地址 ➌,以及它自己的第 2 层 MAC 地址 ➍。

图 7-23:一个邻居请求包
对请求的响应可以在捕获文件的第二个包中找到。展开“包详细信息”窗口中的 ICMPv6 部分(图 7-24)可以看到,该包是 ICMP 类型 136 ➋,从 2001:db8:1:2::1000 发送回 2001:db8:1:2::1003 ➊,并包含与 2001:db8:1:2::1000 相关的 MAC 地址 00:0c:29:1f:a7:55 ➌。

图 7-24:一个邻居广告包
完成此过程后,2001:db8:1:2::1003 和 2001:db8:1:2::1000 将开始正常通信,使用 ICMPv6 回显请求和回复包,表示邻居请求过程和链路层地址解析成功。
IPv6 分片
ipv6_fragments.pcapng
分段支持被内置在 IPv4 头部中,因为它确保了数据包可以在各种网络中传输,而那时网络的最大传输单元(MTU)差异极大。在 IPv6 中,分段的使用较少,因此支持分段的选项没有包含在 IPv6 头部中。传输 IPv6 数据包的设备需要执行一个叫做MTU 发现的过程,以确定它在发送数据包之前可以发送的最大数据包大小。如果路由器接收到一个超出其转发的网络 MTU 的数据包,它将丢弃该数据包并返回一个 ICMPv6 的"数据包过大"(类型 2)消息给源主机。接收到此消息后,源主机会尝试使用更小的 MTU 重新发送数据包(前提是上层协议支持这种操作)。这一过程将不断重复,直到达到足够小的 MTU,或者直到负载无法再进行分段为止(图 7-25)。路由器永远不会自己负责分段数据包;源设备负责确定传输路径的合适 MTU,并适当分段。

图 7-25:IPv6 MTU 路径发现
如果与 IPv6 一起使用的上层协议无法限制数据包负载的大小,则仍然必须使用分段。可以将分段扩展头部添加到 IPv6 数据包中,以支持这种情况。你可以在名为ipv6_fragments.pcapng的文件中找到显示 IPv6 分段的示例捕获。
由于接收设备的 MTU 小于发送设备,因此在捕获文件中,每个 ICMPv6 回显请求和回显应答都有两个分段的数据包。第一个数据包的分段头部如图 7-26 所示。

图 7-26:IPv6 分段头部扩展
8 字节的扩展头部包含了与 IPv4 数据包中相同的所有分段属性,例如分段偏移量 ➋、更多分段标志 ➌ 和标识字段 ➍。它并非出现在每个数据包中,而是仅添加到需要分段的数据包的末尾。这个更高效的过程仍然允许接收系统适当地重新组装分段。此外,如果存在这个扩展头部,下一头部字段将指向扩展头部,而不是封装协议 ➊。
IPv6 过渡协议
IPv6 解决了一个非常实际的问题,但由于将网络基础设施迁移到 IPv6 所需的工作量,其采用速度较慢。为了简化这一过渡,几种协议允许 IPv6 通信通过只支持 IPv4 通信的网络进行隧道传输。在这个意义上,隧道传输意味着 IPv6 通信被封装在 IPv4 通信中,就像其他协议可能被封装一样。封装通常通过三种方式之一进行:
路由器到路由器 使用隧道封装 IPv6 流量,将传输和接收主机的网络上的流量通过 IPv4 网络传输。此方法允许整个网络通过中介 IPv4 链接进行 IPv6 通信。
主机到路由器 在路由器级别使用封装将 IPv6 主机上的流量通过 IPv4 网络进行传输。该方法允许当主机位于仅支持 IPv4 网络时,主机可以在 IPv6 网络中进行 IPv6 通信。
主机到主机 通过两个端点之间的隧道封装 IPv6 流量,实现 IPv4 或 IPv6 主机之间的通信。该方法允许 IPv6 端点直接通过 IPv4 网络进行通信。
尽管本书不会深入讨论过渡协议,但了解它们的存在很有帮助,以防在进行数据包级别的分析时需要研究它们。以下是一些常见的协议:
6to4 也称为IPv6 over IPv4,该过渡协议允许 IPv6 数据包通过 IPv4 网络进行传输。此协议支持中继和路由器提供路由器到路由器、主机到路由器以及主机到主机的 IPv6 通信。
Teredo 该协议用于通过 NAT(网络地址转换)在 IPv4 网络上传输 IPv6 单播通信,其工作原理是将 IPv6 数据包封装在 UDP 传输协议中,通过 IPv4 进行传输。
ISATAP 该站内协议允许在同一网络内进行 IPv4 和 IPv6 设备之间的主机到主机通信。
互联网控制消息协议(ICMP)
互联网控制消息协议(ICMP)是 TCP/IP 的实用协议,负责提供有关 TCP/IP 网络上设备、服务或路由可用性的信息。大多数网络故障排除技术和工具都集中在常见的 ICMP 消息类型上。ICMP 定义在 RFC 792 中。
ICMP 数据包结构
ICMP 是 IP 的一部分,依赖于 IP 来传输其消息。ICMP 包含一个相对较小的头部,根据其目的的不同而变化。如图 7-27 所示,ICMP 头部包含以下字段:
类型 根据 RFC 规范,ICMP 消息的类型或分类。
代码 根据 RFC 规范对 ICMP 消息的子分类。
校验和 用于确保 ICMP 头部和数据在到达时完整无损。
可变 根据类型和代码字段的不同而变化的一部分。

图 7-27:ICMP 头部
ICMP 类型和消息
如前所述,ICMP 数据包的结构取决于其目的,这由类型和代码字段中的值定义。
你可以将 ICMP 类型字段看作是数据包的分类,而代码字段则是其子分类。例如,类型字段的值为 3 表示“目标不可达”。虽然仅凭这些信息可能不足以解决问题,但如果该数据包同时指定了代码字段值为 3,表示“端口不可达”,你就可以推测你尝试通信的端口存在问题。
注意
有关可用 ICMP 类型和代码的完整列表,请参见 http://www.iana.org/assignments/icmp-parameters/.
回显请求与回应
icmp_echo.pcapng
ICMP 最著名的应用就是 ping 工具。Ping 用于测试与设备的连接性。虽然 ping 本身并不是 ICMP 规范的一部分,但它利用了 ICMP 来实现其核心功能。
使用 ping 时,在命令提示符中输入 ping ipaddress,将 ipaddress 替换为你网络中某个设备的实际 IP 地址。如果目标设备已开启,且你的计算机能够与之通信,并且没有防火墙阻止该通信,你应该能够看到对 ping 命令的回应。
图 7-28 中的例子显示了四个成功的回复,展示了其大小、往返时间(或 RTT,指的是数据包到达并接收到回应所需的时间)和使用的 TTL 值。Windows 工具还提供了一个总结,详细列出了发送、接收和丢失的数据包数量。如果通信失败,你应该看到一条信息,告诉你原因。

图 7-28:使用ping命令测试连接性
基本上,ping 命令一次只向设备发送一个数据包,并监听回应来判断是否与该设备存在连接性,如图 7-29 所示。

图 7-29:ping命令仅涉及两个步骤。
注意
虽然 ping 长期以来一直是 IT 领域的基础工具,但当主机防火墙部署时,它的结果可能会有些误导。如今的许多防火墙限制了设备响应 ICMP 数据包的能力。这对安全性非常有利,因为潜在的攻击者使用 ping 来判断主机是否可达时可能会被阻止,但故障排除也变得更加困难——当你知道自己能与设备通信时,ping 设备测试连接性却没有得到回应,可能会让人感到沮丧。
ping 工具的实际应用是一个简单的 ICMP 通信的很好的例子。文件中的数据包 icmp_echo.pcapng 展示了当你运行 ping 时发生的情况。
第一个数据包(见图 7-30)显示主机 192.168.100.138 正在向 192.168.100.1 发送数据包 ➊。当你展开此数据包的 ICMP 部分时,可以通过查看类型和代码字段来确定 ICMP 数据包类型。在这种情况下,数据包类型为 8 ➋,代码为 0 ➌,表示回显请求。(Wireshark 应该会告诉你显示的类型/代码是什么。)这个回显(ping)请求是公式的前半部分。它是一个简单的 ICMP 数据包,通过 IP 发送,包含少量数据。除了类型和代码标识以及校验和之外,我们还有一个用于将请求与回复配对的序列号,并且 ICMP 数据包的可变部分中还包含一个随机文本字符串。

图 7-30:一个 ICMP 回显请求数据包
注意
术语 echo 和 ping 常常可以互换使用,但请记住 ping 实际上是一个工具的名称。ping 工具用于发送 ICMP 回显请求数据包。
该序列中的第二个数据包是对我们请求的回复(见图 7-31)。数据包的 ICMP 部分类型为 0 ➊,代码为 0 ➋,表明这是一个回显回复。由于第二个数据包中的序列号和标识符与第一个数据包相同 ➌,我们知道这个回显回复与前一个数据包中的回显请求相匹配。Wireshark 以大端(BE)和小端(LE)格式显示这些字段的值。换句话说,它根据特定端点处理数据的方式,以不同的顺序表示数据。这个回复数据包还包含与初始请求一起传输的相同的 32 字节数据字符串 ➍。一旦 192.168.100.138 收到第二个数据包,ping 将报告成功。

图 7-31:一个 ICMP 回显回复数据包
请注意,你可以使用 ping 命令的不同变种来增加回显请求中的数据填充大小,这将迫使数据包在各种类型的网络故障排除中进行分段。当你在故障排除需要更小分段大小的网络时,这可能是必需的。
注意
ICMP 回显请求中使用的随机文本可能对潜在攻击者非常有价值。攻击者可以利用此填充中的信息来分析设备使用的操作系统。此外,攻击者还可以将少量数据放入此字段,以便进行隐蔽通信。
traceroute
icmp_traceroute.pcapng
traceroute 工具用于识别从一个设备到另一个设备的路径。在简单的网络中,一条路径可能仅经过一个路由器,或者根本不经过路由器。然而,在复杂的网络中,一个数据包可能需要经过数十个路由器才能到达最终目的地。因此,能够追踪数据包从一个目的地到另一个目的地的确切路径,对于故障排除通信非常关键。
通过使用 ICMP(借助 IP 的一点帮助),traceroute 可以绘制数据包的路径。例如,文件icmp_traceroute.pcapng中的第一个数据包与我们在前一节中看到的回显请求非常相似(见图 7-32)。
在这个捕获中,这些数据包是通过运行命令 tracert 4.2.2.1 生成的。要在 Windows 上使用 traceroute,请在命令提示符下输入 tracert ipaddress,将 ipaddress 替换为你想要探测路径的设备的实际 IP 地址。要在 Linux 或 Mac 上使用 traceroute,请使用命令 traceroute ipaddress。

图 7-32: TTL 值为 1 的 ICMP 回显请求数据包
乍一看,这个数据包似乎是一个简单的回显请求 ➌,从 192.168.100.138 发往 4.2.2.1 ➊,并且数据包中的 ICMP 部分与回显请求数据包的格式完全相同。然而,当你展开这个数据包的 IP 头部时,你会注意到一个奇怪的地方:数据包的 TTL 值被设置为 1 ➋,这意味着数据包将在它遇到的第一个路由器处被丢弃。因为目标地址 4.2.2.1 是一个互联网地址,我们知道在源设备和目标设备之间至少会有一个路由器,所以这个数据包根本无法到达目的地。对我们来说,这正是我们需要的,因为 traceroute 依赖于这一点,即这个数据包只会到达它经过的第一个路由器。
第二个数据包,如预期的那样,是我们到达路径上第一个路由器的回复(见图 7-33)。该数据包到达了 192.168.100.1 这个设备,它的 TTL 被减为 0,数据包无法进一步传输,因此路由器回复了一个 ICMP 响应。这个数据包的类型为 11 ➊,代码为 0 ➋,数据告诉我们目的地不可达,因为数据包在传输过程中 TTL 被超出了。
这个 ICMP 数据包有时被称为 双头数据包,因为其 ICMP 部分的尾端包含了在原始回显请求中发送的 IP 头部 ➌ 和 ICMP 数据 ➍ 的副本。这些信息对于故障排除非常有用。

图 7-33: 来自路径上第一个路由器的 ICMP 响应
发送 TTL 值为 1 的数据包这一过程会重复两次,直到我们到达第 7 个数据包。在这里,你看到的与第一个数据包中看到的相同,只是这次,IP 头部中的 TTL 值被设置为 2,这确保数据包在被丢弃之前会到达第二跳路由器。如预期所示,我们从下一个跳的路由器 12.180.241.1 收到回复,包含相同的 ICMP 目的地不可达和 TTL 超过消息。
这个过程会持续进行,TTL 值每次增加 1,直到目的地 4.2.2.1 到达。然而,正如在图 7-34 中所看到的,在线路 8 上,请求超时了。那么,沿着路径的请求如何超时而过程仍能成功完成呢?通常,这发生在路由器配置为不响应 ICMP 请求时。路由器仍然接收到请求并将数据转发给下一个路由器,这就是为什么我们能在图 7-34 中的第 9 行看到下一个跳点。只不过它没有像其他跳点那样生成 ICMP 时间超时的包。由于没有响应,tracert 假定请求超时并继续进行到下一个请求。
总结来说,这个 traceroute 过程已经与路径上的每个路由器进行了通信,构建了通向目的地的路由图。在图 7-34 中显示了一个示例图。

图 7-34:traceroute 工具的示例输出
注意
这里关于 traceroute 的讨论主要集中在 Windows 系统,因为这个工具仅使用 ICMP。Linux 上的 traceroute 工具则更为多功能,可以利用其他协议来执行路径追踪。
ICMP 版本 6(ICMPv6)
更新版的 IP 在诸如邻居请求和路径发现等功能上严重依赖 ICMP,如前面的示例所示。ICMPv6是在 RFC 4443 中建立的,支持 IPv6 所需的功能集以及额外的增强功能。由于 ICMPv6 与 ICMP 数据包使用相同的数据包结构,因此本书不单独讨论 ICMPv6。
ICMPv6 数据包通常分为错误消息或信息消息。你可以从 IANA 找到完整的类型和代码列表,网址是:http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml。
本章介绍了在数据包分析过程中将会涉及到的几个最重要的协议。ARP、IP 和 ICMP 是所有网络通信的基础,它们对你每天要执行的几乎所有任务至关重要。在第八章中,我们将讨论常见的传输层协议,TCP 和 UDP。
第八章:传输层协议

在本章中,我们将继续研究各个协议及其在数据包级别的表现。向上走到 OSI 模型,我们将讨论传输层和两种最常见的传输协议,TCP 和 UDP。
传输控制协议(TCP)
传输控制协议(TCP) 的最终目标是提供端到端的数据传输可靠性。TCP 在 RFC 793 中定义,负责数据排序和错误恢复,并最终确保数据能够到达预定目标。TCP 被认为是 面向连接的协议,因为它在传输数据之前会建立正式的连接,跟踪数据包的传递,通常还会在传输完成后正式关闭通信通道。许多常用的应用层协议依赖于 TCP 和 IP 来将数据包传递到最终目的地。
TCP 数据包结构
TCP 提供了大量功能,正如其头部的复杂性所反映的那样。如 图 8-1 所示,以下是 TCP 头部字段:
源端口 用于传输数据包的端口。
目标端口 数据包将传输到的端口。
序列号 用于标识 TCP 段的编号。该字段用于确保数据流的部分数据不丢失。
确认号 在通信的另一方预计会在下一个数据包中发送的序列号。
标志 用于标识正在传输的 TCP 数据包类型的 URG、ACK、PSH、RST、SYN 和 FIN 标志。
窗口大小 TCP 接收缓冲区的大小(以字节为单位)。
校验和 用于确保到达时 TCP 头部和数据的内容完整无误。
紧急指针 如果设置了 URG 标志,则检查此字段以获取额外的指令,告诉 CPU 从数据包中的何处开始读取数据。
选项 可以在 TCP 数据包中指定的各种可选字段。

图 8-1:TCP 头部
TCP 端口
tcp_ports.pcapng
所有 TCP 通信都使用源端口和目标端口,这可以在每个 TCP 头部中找到。端口就像旧电话交换机上的插孔。交换机操作员会监视一板灯光和插孔。当灯亮起时,他会接通来电者,询问她想联系谁,然后通过插入电缆将她连接到另一方。每个电话都需要有源端口(来电者)和目标端口(接收者)。TCP 端口的工作方式非常相似。
为了将数据传输到远程服务器或设备上的特定应用程序,TCP 数据包必须知道远程服务正在监听的端口。如果尝试访问未配置用于访问的端口上的应用程序,通信将失败。
这个序列中的源端口并不是非常重要,可以随机选择。远程服务器会从发送的原始数据包中确定与之通信的端口(参见图 8-2)。

图 8-2:TCP 使用端口传输数据。
在与 TCP 通信时,有 65,535 个端口可供使用。我们通常将这些端口分为两组:
系统端口组(也称为标准端口或知名端口组)的范围从 1 到 1023(忽略 0,因为它是保留的)。知名的、已建立的服务通常使用位于系统端口组内的端口。
临时端口组的范围从 1024 到 65535(尽管一些操作系统对这一范围有不同的定义)。在任何给定时刻,只有一个服务可以在某个端口上进行通信,因此现代操作系统会随机选择源端口,以便使通信具有唯一性。这些源端口通常位于临时端口范围内。
让我们检查几个 TCP 数据包,并通过打开文件tcp_ports.pcapng来识别它们使用的端口号。在这个文件中,我们有一个客户端浏览两个网站的 HTTP 通信。如前所述,HTTP 使用 TCP 进行通信,这使它成为标准 TCP 流量的一个很好的示例。
在此文件中的第一个数据包中(参见图 8-3),前两个值表示数据包的源端口和目标端口。该数据包正从 172.16.16.128 发送到 212.58.226.142。源端口是 2826 ➊,一个临时端口。(请记住,源端口是由操作系统随机选择的,尽管它们可以从该随机选择中递增。)目标端口是一个系统端口,端口 80 ➋,这是用于使用 HTTP 的 Web 服务器的标准端口。

图 8-3:源端口和目标端口可以在 TCP 头部找到。
注意,Wireshark 将这些端口标记为 slc-systemlog(2826)和 http(80)。Wireshark 维护着一份端口及其最常见用途的列表。尽管系统端口是主要具有常见用途标签的端口,但许多临时端口也与常用服务相关联。由于这些端口的标签可能会让人困惑,因此通常最好通过关闭传输名称解析来禁用它。操作方法是:进入编辑 ▶ 首选项 ▶ 名称解析,然后取消选中启用传输名称解析。如果你希望保留此选项,但想要更改 Wireshark 如何识别某个端口,可以通过修改位于 Wireshark 系统目录中的services文件来实现。该文件的内容基于 IANA 的常见端口列表(参见第 86 页的“使用自定义主机文件”部分,了解如何编辑名称解析文件的示例)。
第二个数据包从 212.58.226.142 发送回 172.16.16.128(见图 8-4)。与 IP 地址一样,源端口和目标端口现在也被切换 ➊。
在大多数情况下,基于 TCP 的通信工作方式相同:选择一个随机的源端口与已知的目标端口进行通信。发送此初始数据包后,远程设备将使用已建立的端口与源设备进行通信。
这个示例捕获文件包含了一个额外的通信流。看看你能否找到它在通信中使用的端口号。

图 8-4:切换源端口和目标端口号以实现反向通信
注意
随着本书的深入,你将了解更多关于常见协议和服务相关的端口。最终,你将能够通过它们使用的端口来对服务和设备进行分析。有关常见端口的完整列表,请查看位于 Wireshark 系统目录中的 services 文件。
TCP 三次握手
所有基于 TCP 的通信都必须从两台主机之间的 握手 开始。此握手过程有几个目的:
• 它允许发送方主机确保接收方主机处于运行状态并能够进行通信。
• 它让发送方主机检查接收方是否在发送方尝试通信的端口上监听。
tcp_handshake.pcapng
• 它允许发送方主机将其起始序列号发送给接收方,以便两台主机能够保持数据包流的正确顺序。
TCP 握手过程分为三个步骤,如图 8-5 所示。在第一步,想要进行通信的设备(主机 A)向其目标(主机 B)发送一个 TCP 数据包。这个初始数据包除了底层协议头部外不包含其他数据。该数据包中的 TCP 头部设置了 SYN 标志,并包括将用于通信过程中的初始序列号和最大报文段大小(MSS)。主机 B 对此数据包做出响应,发送一个类似的数据包,设置 SYN 和 ACK 标志,并带有其初始序列号。最后,主机 A 向主机 B 发送最后一个数据包,仅设置 ACK 标志。一旦这个过程完成,两个设备应该就拥有开始正常通信所需的所有信息。
注意
TCP 数据包通常通过其设置的标志来命名。例如,我们不说“设置了 SYN 标志的 TCP 数据包”,而是称其为 SYN 数据包。因此,在 TCP 握手过程中使用的数据包分别称为 SYN、SYN/ACK 和 ACK。
要查看这个过程的实际操作,请打开tcp_handshake.pcapng。Wireshark 提供了一个功能,可以将 TCP 数据包的序列号替换为相对序列号,以便更轻松地进行分析。为了我们的目的,我们将禁用此功能,以查看实际的序列号。要禁用此功能,请选择编辑 ▶ 首选项,展开协议部分,然后选择TCP。在窗口中,取消勾选相对序列号旁边的框,并点击确定。

图 8-5:TCP 三次握手
该捕获中的第一个数据包代表我们的初始 SYN 数据包 ➋(参见图 8-6)。该数据包从 172.16.16.128 的 2826 端口发送到 212.58.226.142 的 80 端口。我们可以看到这里传输的序列号是 3691127924 ➊。
握手中的第二个数据包是来自 212.58.226.142 的 SYN/ACK 响应 ➌(参见图 8-7)。该数据包还包含此主机的初始序列号(233779340) ➊ 和一个确认号(3691127925) ➋。这里显示的确认号比前一个数据包中的序列号大 1,因为该字段用于指定主机预计接收到的下一个序列号。
最后的数据包是从 172.16.16.128 发送的 ACK ➋ 数据包(参见图 8-8)。这个数据包,正如预期的那样,包含了序列号 3691127925 ➊,该序列号如前一个数据包的确认号字段所定义。
每次 TCP 通信序列开始前都会发生握手。当你在忙碌的捕获文件中查找通信序列的开始时,序列 SYN-SYN/ACK-ACK 是一个很好的标记。

图 8-6:初始 SYN 数据包

图 8-7:SYN/ACK 响应

图 8-8:最终的 ACK
TCP 拆除
tcp_teardown.pcapng
大多数问候语最终都会有告别,TCP 的情况也是如此,每次握手后都有拆除过程。TCP 拆除用于在两个设备完成通信后,优雅地结束它们之间的连接。这个过程涉及四个数据包,并利用 FIN 标志来表示连接的结束。
在拆除序列中,主机 A 通过发送一个设置了 FIN 和 ACK 标志的 TCP 数据包,告诉主机 B 它已完成通信。主机 B 用一个 ACK 数据包响应,并发送它自己的 FIN/ACK 数据包。主机 A 以一个 ACK 数据包作出响应,结束通信。这个过程在图 8-9 中进行了说明。

图 8-9:TCP 拆除过程
要在 Wireshark 中查看此过程,请打开文件 tcp_teardown.pcapng。从序列中的第一个数据包开始(参见图 8-10),你可以看到位于 67.228.110.120 的设备通过发送一个设置了 FIN 和 ACK 标志的数据包 ➊ 来启动拆除过程。

图 8-10:FIN/ACK 数据包启动了断开连接的过程。
一旦发送了这个数据包,172.16.16.128 将通过 ACK 数据包响应,以确认收到第一个数据包,并发送一个 FIN/ACK 数据包。当 67.228.110.120 发送最终的 ACK 数据包时,过程完成。此时,两个设备之间的通信结束。如果它们需要再次开始通信,则必须完成新的 TCP 握手过程。
TCP 重置
tcp_refuseconnection.pcapng
在理想的世界中,每个连接都会优雅地以 TCP 断开过程结束。实际上,连接往往会突然终止。例如,主机可能配置错误,或者潜在的攻击者可能进行端口扫描。在这些情况下,当数据包被发送到一个不愿意接收它的设备时,可能会发送一个带有 RST 标志的 TCP 数据包。RST 标志用于表示连接被突然关闭或拒绝连接请求。
文件 tcp_refuseconnection.pcapng 显示了一个包含 RST 数据包的网络流量示例。该文件中的第一个数据包来自 IP 地址为 192.168.100.138 的主机,它正在尝试与 192.168.100.1 的端口 80 通信。这个主机并不知道的是,192.168.100.1 并没有在端口 80 上监听,因为它是一个没有配置 Web 界面的 Cisco 路由器,该端口没有配置任何接受连接的服务。作为对这种尝试通信的响应,192.168.100.1 向 192.168.100.138 发送了一个数据包,告知它无法通过端口 80 进行通信。图 8-11 显示了这种通信尝试在第二个数据包的 TCP 头部中的突然结束。该 RST 数据包仅包含 RST 和 ACK 标志 ➊,且没有进一步的通信。

图 8-11:RST 和 ACK 标志表示通信结束。
无论 RST 数据包是在尝试通信序列的开始时到达(如本例所示),还是在主机之间的通信中间发送,它都能结束通信。
用户数据报协议(UDP)
udp_dnsrequest.pcapng
用户数据报协议(UDP) 是现代网络中常用的另一种第四层协议。虽然 TCP 设计用于可靠的数据传输并内建错误检测,但 UDP 旨在提供快速传输。因此,UDP 是一种尽力而为的服务,通常被称为 无连接协议。无连接协议不像 TCP 那样正式地建立和终止主机之间的连接,它没有握手和断开连接的过程。
使用无连接协议的情况下,UDP 流量看起来最多也只是零散的。然而,这种情况并不完全准确,因为依赖 UDP 的协议通常具有内置的可靠性服务,或利用 ICMP 的某些特性使连接更加可靠。例如,应用层协议 DNS 和 DHCP,高度依赖于数据包在网络中传输的速度,使用 UDP 作为它们的传输层协议,但它们自行处理错误检查和重传定时器。
UDP 数据包结构
udp_dnsrequest.pcapng
UDP 头部比 TCP 头部小得多,也更简单。如图 8-12 所示,以下是 UDP 头部字段:
源端口 用于传输数据包的端口
目标端口 数据包将被传输到的端口
数据包长度 数据包的字节长度
校验和 用于确保 UDP 头部和数据内容到达时未被损坏

图 8-12:UDP 头部
文件 udp_dnsrequest.pcapng 包含一个数据包。该数据包表示一个 DNS 请求,使用 UDP 协议。当你展开该数据包的 UDP 头部时,你会看到四个字段(见图 8-13)。

图 8-13:UDP 数据包的内容非常简单。
需要记住的关键点是,UDP 不关心可靠交付。因此,任何使用 UDP 的应用程序如果需要可靠交付,必须采取特殊步骤确保这一点。这与 TCP 相反,TCP 使用正式的连接建立和拆除过程,并具备验证数据包是否成功传输的功能。
本章介绍了传输层协议 TCP 和 UDP。与网络协议类似,TCP 和 UDP 是大多数日常通信的核心,能够有效分析它们对于成为一个高效的数据包分析员至关重要。在第九章,我们将介绍常见的应用层协议。
第九章:常见上层协议

在本章中,我们将继续探讨各个协议的功能,以及使用 Wireshark 查看时它们的表现。我们将讨论五种最常见的上层(第 7 层)协议:DHCP、DNS、HTTP 和 SMTP。
动态主机配置协议(DHCP)
在网络发展的早期,当设备希望通过网络进行通信时,需要手动分配一个地址。随着网络的扩展,这一手动过程迅速变得繁琐。为了解决这个问题,创建了引导协议(BOOTP)来自动为网络连接的设备分配地址。后来,BOOTP 被更先进的动态主机配置协议(DHCP)所取代。
DHCP 是一个应用层协议,负责允许设备自动获取 IP 地址(以及其他重要的网络资源地址,如 DNS 服务器和路由器)。如今,大多数 DHCP 服务器还会向客户端提供其他参数,例如默认网关和网络中使用的 DNS 服务器的地址。
DHCP 数据包结构
DHCP 数据包可以携带相当多的信息给客户端。如图 9-1 所示,DHCP 数据包中包含以下字段:
操作码 表示数据包是 DHCP 请求还是 DHCP 回复
硬件类型 硬件地址的类型(10MB 以太网、IEEE 802、ATM 等)
硬件长度 硬件地址的长度
跳数 由中继代理使用,帮助查找 DHCP 服务器
事务 ID 用于将请求与响应配对的随机数字
已用秒数 客户端从第一次向 DHCP 服务器请求地址以来的秒数
标志 DHCP 客户端可以接受的流量类型(单播、广播等)

图 9-1:DHCP 数据包结构
客户端 IP 地址 客户端的 IP 地址(源自“您的 IP 地址”字段)
您的 IP 地址 DHCP 服务器提供的 IP 地址(最终成为客户端 IP 地址字段的值)
服务器 IP 地址 DHCP 服务器的 IP 地址
网关 IP 地址 网络默认网关的 IP 地址
客户端硬件地址 客户端的 MAC 地址
服务器主机名 服务器的主机名(可选)
引导文件 用于 DHCP 的引导文件(可选)
选项 用于扩展 DHCP 数据包结构,赋予其更多功能
DHCP 初始化过程
dhcp_nolease _initialization.pcapng
DHCP 的主要目标是在初始化过程中为客户端分配地址。续租过程发生在单个客户端和 DHCP 服务器之间,如文件dhcp_nolease_initialization.pcapng所示。DHCP 初始化过程通常称为 DORA 过程,因为它使用四种类型的 DHCP 数据包:发现、提供、请求和确认,如图 9-2 所示。在这里,我们将逐一查看每种类型的 DORA 数据包。

图 9-2:DHCP DORA 过程
发现数据包
如你在引用的捕获文件中所见,第一个数据包是从 0.0.0.0 的 68 端口发送到 255.255.255.255 的 67 端口。客户端使用 0.0.0.0,因为它还没有 IP 地址。该数据包发送到 255.255.255.255,因为这是一个与网络无关的广播地址,从而确保该数据包将被发送到网络上的每个设备。由于设备不知道 DHCP 服务器的地址,因此此第一个数据包是为了尝试寻找一个会监听的 DHCP 服务器。
查看数据包详细信息窗格时,首先注意到的是 DHCP 依赖 UDP 作为其传输层协议。DHCP 非常关注客户端接收请求信息的速度。DHCP 具有内置的可靠性措施,这意味着 UDP 非常适合。你可以通过查看数据包详细信息窗格中的第一个数据包的 DHCP 部分,来查看发现过程的细节,如图 9-3 所示。

图 9-3:DHCP 发现数据包
注意
由于 Wireshark 在处理 DHCP 时仍参考 BOOTP,因此你将在数据包详细信息窗格中看到一个 Bootstrap 协议部分,而不是 DHCP 部分。然而,在本书中我会将其称为数据包的DHCP 部分。
该数据包是一个请求,由消息类型字段中的(1)标识 ➊。此发现数据包中的大多数字段要么全为零(如你在 IP 地址字段 ➋中看到的那样),要么根据上一节中列出的 DHCP 字段的说明非常容易理解。这个数据包的核心内容在于其四个选项字段 ➌。
DHCP 消息类型 这是选项类型53,长度为1,值为Discover (1)。这些值表明这是一个 DHCP 发现数据包。
客户端标识符 提供有关请求 IP 地址的客户端的额外信息。
请求的 IP 地址 提供客户端希望接收的 IP 地址。这可以是之前使用过的 IP 地址,或者是 0.0.0.0 以表示没有偏好。
参数请求列表 列出了客户端希望从 DHCP 服务器接收的不同配置项(其他重要网络设备的 IP 地址以及其他非 IP 项目)。
提供数据包
本文件中的第二个数据包列出了其 IP 头中的有效 IP 地址,显示一个从 192.168.1.5 到 192.168.1.10 的数据包,如 图 9-4 所示。客户端实际上还没有 192.168.1.10 地址,因此服务器将首先尝试使用 ARP 提供的硬件地址与客户端进行通信。如果通信不可行,服务器将简单地广播该响应以进行通信。
这个第二个数据包的 DHCP 部分,被称为 响应数据包,表明消息类型是回复 ➊。该数据包包含与前一个数据包相同的事务 ID ➋,这告诉我们这个回复确实是对我们原始请求的回应。
响应数据包是由 DHCP 服务器发送的,目的是向客户端提供服务。它通过提供关于自身以及它希望提供给客户端的地址信息来完成此操作。在 图 9-4 中,IP 地址 192.168.1.10 在“您的(客户端)IP 地址”字段中被提供给客户端 ➌,该地址由“下一服务器 IP 地址”字段中的 192.168.1.5 标识 ➍。
第一个列出的选项将数据包标识为 DHCP 响应 ➎。后续的选项由服务器提供,并指示它可以提供的附加信息,以及客户端的 IP 地址。你可以看到它提供了以下内容:
• IP 地址租用时间为 10 分钟
• 子网掩码为 255.255.255.0
• 广播地址为 192.168.1.255
• 路由器地址为 192.168.1.254
• 一个域名 mydomain.example
• 域名服务器地址为 192.168.1.1 和 192.168.1.2

图 9-4:DHCP 响应数据包
请求数据包
一旦客户端收到来自 DHCP 服务器的响应,它应该通过一个 DHCP 请求数据包接受该响应,如 图 9-5 所示。
这个捕获中的第三个数据包仍然来自 IP 地址 0.0.0.0,因为我们还没有完成获取 IP 地址的过程 ➊。此数据包现在已经知道它正在与哪个 DHCP 服务器通信。

图 9-5:DHCP 请求数据包
消息类型字段显示该数据包是一个请求 ➋,而事务 ID 字段与前两个数据包相同 ➌,这表明它们属于同一过程。此数据包类似于发现数据包,因为其所有 IP 地址信息都被置为零。
最后,在选项字段中,我们看到这是一条 DHCP 请求 ➍。请注意,请求的 IP 地址不再为空,且 DHCP 服务器标识符字段也包含了一个地址 ➎。
确认数据包
在这个过程的最后一步,DHCP 服务器通过确认数据包将请求的 IP 地址发送给客户端,并将该信息记录在其数据库中,如 图 9-6 所示。客户端现在已经有了一个 IP 地址,并可以开始在网络上进行通信。

图 9-6:DCHP 确认包
DHCP 租用续期
dhcp_inlease_renewal.pcapng
当 DHCP 服务器为设备分配 IP 地址时,它会将该地址租用给客户端。这意味着客户端只能在有限的时间内使用该 IP 地址,之后必须续租。前面讨论的 DORA 过程发生在客户端第一次获取 IP 地址或其租期已到期时。在这两种情况下,设备都被视为租期结束。
当一个带有租用 IP 地址的客户端重启时,它必须执行简化版的 DORA 过程以重新获得其 IP 地址。这个过程叫做租用续期。
在租期续期的情况下,发现和提供数据包是不必要的。可以把租期续期看作是与租期结束续期相同的 DORA 过程,但租期续期不需要做太多的工作,仅剩下请求和确认步骤。你可以在文件dhcp_inlease_renewal.pcapng中找到租期续期的示例抓包。
DHCP 选项和消息类型
DHCP 的真正灵活性体现在其可用选项上。正如你所看到的,数据包的 DHCP 选项可以在大小和内容上有所不同。数据包的总体大小取决于所使用的选项组合。你可以在* www.iana.org/assignments/bootp-dhcp-parameters/*查看所有 DHCP 选项的完整列表。
所有 DHCP 数据包中唯一必需的选项是消息类型选项(选项 53)。此选项用于标识 DHCP 客户端或服务器如何处理数据包中的信息。消息类型共有 8 种,如表 9-1 所定义。
表 9-1:DHCP 消息类型
| 类型编号 | 消息类型 | 描述 |
|---|---|---|
| 1 | Discover | 客户端用来定位可用的 DHCP 服务器 |
| 2 | Offer | 服务器响应发现数据包时发送给客户端 |
| 3 | Request | 客户端发送给服务器,请求提供的参数 |
| 4 | Decline | 客户端发送给服务器,指示数据包内的参数无效 |
| 5 | ACK | 由服务器发送给客户端,包含客户端请求的配置信息 |
| 6 | NAK | 客户端发送给服务器,用于拒绝配置参数请求 |
| 7 | Release | 客户端发送给服务器,取消租约并释放其配置参数 |
| 8 | Inform | 客户端发送给服务器,请求配置参数,当客户端已拥有 IP 地址时 |
DHCP 版本 6(DHCPv6)
dhcp6_outlease_acquisition.pcapng
如果你查看图 9-1 中 DHCP 数据包的结构,你会发现它没有足够的空间来支持 IPv6 地址分配所需的长度。为了不将 DHCP 修改用于此目的,RFC3315 中设计了 DHCPv6。由于 DHCPv6 并不是基于 BOOTP 的概念,它的数据包格式要简单得多(见图 9-7)。

图 9-7:DHCPv6 数据包结构
这里显示的数据包结构仅包含两个静态值,它们的作用与 DHCP 中的对应值相同。数据包结构的其余部分根据第一个字节中标识的消息类型而变化。在选项部分,每个选项都通过 2 字节的选项代码和 2 字节的长度字段进行标识。有关这些字段中可能出现的消息类型和选项代码的完整列表,请访问: www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml。
DHCPv6 达成的目标与 DHCP 相同,但要理解 DHCPv6 通信的流程,我们必须用一个新的缩写词 SARR 来替换原有的 DORA。这个过程在图 9-8 中有所示,图中代表了一个当前超出租期的客户端。

图 9-8:DHCPv6 SARR 超出租期续租过程
SARR 过程有四个步骤:
-
请求:客户端从客户端向特殊的多播地址(ff02::1:2)发送初始数据包,尝试在网络上定位可用的 DHCPv6 服务器。
-
广告:可用的服务器直接响应客户端,表明它可以提供地址分配和配置信息。
-
请求:客户端通过多播向服务器发送正式的配置信息请求。
-
回复:服务器将所有可用的请求配置信息直接发送给客户端,过程完成。
这个过程的总结显示在图 9-9 中,取自文件 dhcp6_outlease_acquisition.pcapng。在这个示例中,我们可以看到 SARR 过程的实际操作,新的主机(fe80::20c:29ff:fe5e:7744)从 DHCPv6 服务器(fe80::20c:29ff:fe1f:a755)接收到配置信息。每个数据包代表 SARR 过程的一个步骤,初始的请求和广告数据包通过事务 ID 0x9de03f 连接在一起,请求和回复数据包通过事务 ID 0x2d1603 关联。尽管图中没有显示,但这种通信是通过端口 546 和 547 进行的,这是 DHCPv6 使用的标准端口。

图 9-9:客户端通过 DHCPv6 获取 IPv6 地址
总体而言,DHCPv6 流量的包结构看起来与我们之前讨论的包类型有很大不同,但大多数相同的概念依然适用。该过程仍然需要某种形式的 DHCP 服务器发现,并正式检索配置信息。这些事务通过客户端和服务器之间交换的每对数据包中的事务标识符关联在一起。传统的 DHCP 机制无法支持 IPv6 地址分配,因此,如果你的设备从网络中的服务器自动获取 IPv6 地址,可能已经在网络上运行 DHCPv6 服务。如果你想进一步比较 DHCP 和 DHCPv6,我建议你并排查看本章讨论的数据包捕获,并逐步分析它们。
域名系统(DNS)
域名系统(DNS)是互联网上最重要的协议之一,因为它就像粘合剂一样,将网络中的各个部分联系在一起。DNS 将域名(例如 www.google.com)与 IP 地址(例如 74.125.159.99)关联。当我们想与网络设备通信,而又不知道其 IP 地址时,我们通过其 DNS 名称访问该设备。
DNS 服务器存储 IP 地址与 DNS 名称映射的资源记录数据库,并与客户端和其他 DNS 服务器共享这些记录。
注意
由于 DNS 服务器的架构较为复杂,我们只关注一些常见的 DNS 流量类型。你可以在 www.isc.org/community/rfcs/dns/ 查看各种与 DNS 相关的 RFC 文档。
DNS 数据包结构
正如你在图 9-10 中看到的,DNS 数据包的结构与我们之前讨论的数据包类型略有不同。DNS 数据包中可以包含以下字段:
DNS ID 号 用于将 DNS 查询与 DNS 响应关联
查询/响应(QR) 表示数据包是 DNS 查询还是响应
操作码(OpCode) 定义消息中查询的类型
权威回答(AA) 如果此值在响应数据包中设置,表示该响应来自具有该域名权威的名称服务器
截断(TC) 表示响应被截断,因为它太大,无法放入数据包中
递归请求(RD) 当此值在查询中设置时,表示如果目标名称服务器没有包含所请求的信息,DNS 客户端请求递归查询
递归可用(RA) 如果此值在响应中设置,表示名称服务器支持递归查询

图 9-10:DNS 数据包结构
保留(Z) 根据 RFC 1035 定义,应该设置为全零;然而,有时它被用作 RCode 字段的扩展
响应码(RCode) 用于 DNS 响应中,表示是否存在错误
问题计数 问题部分中的条目数
回答数量 回答部分中的条目数量
名称服务器(授权)记录数量 授权部分中名称服务器资源记录的数量
附加记录数量 附加信息部分中其他资源记录的数量
问题部分 可变大小的部分,包含一个或多个查询,用于向 DNS 服务器发送信息
回答部分 可变大小的部分,包含一个或多个资源记录,用于回答查询
授权部分 可变大小的部分,包含指向授权名称服务器的资源记录,这些服务器可以用于继续解析过程
附加信息部分 可变大小的部分,包含与查询相关的附加资源记录,这些记录对于回答查询并非绝对必要
一个简单的 DNS 查询
dns_query_response.pcapng
DNS 以查询-响应格式工作。希望将 DNS 名称解析为 IP 地址的客户端向 DNS 服务器发送一个 查询,然后服务器在其 响应 中返回请求的信息。在最简单的形式下,这个过程需要两个数据包,正如在捕获文件 dns_query_response.pcapng 中看到的那样。
第一个数据包,如 图 9-11 所示,是客户端 192.168.0.114 向服务器 205.152.37.23 发送的 DNS 查询,目标端口为 53,这是 DNS 使用的标准端口。

图 9-11:DNS 查询数据包
当你开始检查这个数据包中的头部时,你会发现 DNS 也依赖于 UDP ➊。
在数据包的 DNS 部分,你可以看到数据包开头的较小字段被 Wireshark 压缩成了一个单独的标志部分。展开此部分,你会看到该消息确实是一个标准查询 ➋,它没有被截断,并且需要递归(稍后我们会讲解递归)。这里只识别了一个问题,可以通过展开查询部分来查看。你会看到该查询是针对 wireshark.org 域名的一个主机(类型 A)互联网(IN)地址 ➌。这个数据包基本上是在问:“哪个 IP 地址与 wireshark.org 域名关联?”
对该请求的响应在数据包 2 中,如 图 9-12 所示。因为这个数据包有相同的标识号 ➊,我们知道它包含对原始查询的正确响应。
Flags 部分确认这是一个响应,如果需要,可以使用递归 ➋。此数据包仅包含一个问题和一个资源记录 ➌,因为它包括原始问题及其答案。展开 Answers 部分,我们可以看到查询的响应:wireshark.org 的 IP 地址是 128.121.50.122 ➍。通过此信息,客户端现在可以构建 IP 数据包并开始与 wireshark.org 通信。

图 9-12:DNS 响应数据包
DNS 查询类型
在 DNS 查询和响应中使用的 Type 字段表示查询或响应的资源记录类型。一些常见的消息/资源记录类型列在 表 9-2 中。在正常流量和本书中,您将看到这些类型。(表 9-2 中的列表很简短,并且并非详尽无遗。如需查看所有 DNS 资源记录类型,请访问 www.iana.org/assignments/dns-parameters/。)
表 9-2: 常见的 DNS 资源记录类型
| 值 | 类型 | 描述 |
|---|---|---|
| 1 | A | IPv4 主机地址 |
| 2 | NS | 权威名称服务器 |
| 5 | CNAME | 别名的规范名称 |
| 15 | MX | 邮件交换 |
| 16 | TXT | 文本字符串 |
| 28 | AAAA | IPv6 主机地址 |
| 251 | IXFR | 增量区域传输 |
| 252 | AXFR | 完整区域传输 |
DNS 递归
dns_recursivequery_client.pcapng, dns_recursivequery_server.pcapng
由于互联网 DNS 结构的层次性,DNS 服务器必须能够相互通信,以回答客户端提交的查询。虽然我们期望内部 DNS 服务器知道我们本地内部网络服务器的名称到 IP 地址的映射,但我们不能指望它知道 Google 或 Dell 的关联 IP 地址。
当 DNS 服务器需要查找 IP 地址时,它会代表客户端向另一台 DNS 服务器发起查询,实际上充当客户端的角色。这个过程称为 递归。
要从 DNS 客户端和服务器的角度查看递归过程,请打开文件 dns_recursivequery_client.pcapng。此文件包含一个客户端的 DNS 流量捕获文件,包含两个数据包。第一个数据包是从 DNS 客户端 172.16.0.8 发往其 DNS 服务器 172.16.0.102 的初始查询,如 图 9-13 所示。

图 9-13:设置了递归请求标志的 DNS 查询
当您展开此数据包的 DNS 部分时,您将看到这是一个标准查询,请求 DNS 名称 www.nostarch.com 的 A 类型记录 ➋。要了解更多关于此数据包的信息,请展开 Flags 部分,您将看到需要递归 ➊。
第二个数据包是我们期望看到的对初始查询的响应,如图 9-14 所示。

图 9-14:DNS 查询响应
这个数据包的事务 ID 与我们的查询 ➊ 匹配,没有列出任何错误,我们收到了与 www.nostarch.com 相关联的 A 类型资源记录 ➋。
我们可以通过监听 DNS 服务器的流量来看到此查询是通过递归方式得到回答的,正如文件 dns_recursivequery_server.pcapng 所示。该文件展示了当查询发起时本地 DNS 服务器的流量捕获(图 9-15)。

图 9-15:从服务器的角度看 DNS 递归
第一个数据包是我们在前一个捕获文件中看到的相同初始查询。此时,DNS 服务器已经收到查询,检查了其本地数据库,并意识到它不知道哪个 IP 地址与 DNS 名称 (www.nostarch.com) 对应。由于数据包是带着“需要递归”标志发送的,DNS 服务器可以向另一个 DNS 服务器提出这个问题,试图找到答案,正如你在第二个数据包中看到的那样。
在第二个数据包中,位于 172.16.0.102 的 DNS 服务器向 4.2.2.1 发送了一个新的查询 ➊,这是它配置转发上游请求的服务器,如图 9-16 所示。这个查询与原始查询相同,实际上将 DNS 服务器变成了一个客户端。我们可以通过事务 ID 号与前一个捕获文件中的事务 ID 号不同来判断这是一个新的查询 ➋。

图 9-16:递归 DNS 查询
一旦服务器 4.2.2.1 收到这个数据包,局部 DNS 服务器就会收到如图 9-17 所示的响应。

图 9-17:递归 DNS 查询的响应
收到这个响应后,局部 DNS 服务器可以将第四个也是最后一个数据包传送给 DNS 客户端,包含所请求的信息。
尽管这个例子只展示了单层递归,但对于单个 DNS 请求,递归可能会发生多次。在这里,我们从 DNS 服务器 4.2.2.1 收到了回答,但该服务器可能已经将查询递归地转发到另一个服务器以找到答案。一个简单的查询可能会在全球范围内传输,直到最终收到正确的响应。图 9-18 展示了递归 DNS 查询的过程。

图 9-18:递归 DNS 查询
DNS 区域传输
dns_axfr.pcapng
一个DNS 区域是 DNS 服务器被委托管理的命名空间(或 DNS 名称组)。例如,Emma’s Diner 可能有一个 DNS 服务器负责* emmasdiner.com 。在这种情况下,想要将 emmasdiner.com 解析为 IP 地址的设备,无论是在 Emma’s Diner 内部还是外部,都需要联系该 DNS 服务器作为该区域的权威。如果 Emma’s Diner 扩展业务,它可以增加第二个 DNS 服务器,仅处理其 DNS 命名空间中的电子邮件部分,例如 mail.emmasdiner.com *,该服务器将成为该邮件子域的权威。如图 9-19 所示,可能会根据需要为子域添加额外的 DNS 服务器。

图 9-19:DNS 区域划分了命名空间的责任。
一个区域传输发生在区域数据在两个设备之间传输时,通常是出于冗余的需求。例如,在有多个 DNS 服务器的组织中,管理员通常会配置一个辅助 DNS 服务器,以保持主服务器 DNS 区域信息的副本,以防主服务器不可用。区域传输有两种类型:
完整区域传输(AXFR) 这些类型的传输在设备之间发送整个区域。
增量区域传输(IXFR) 这些类型的传输只发送部分区域信息。
文件dns_axfr.pcapng包含了主机 172.16.16.164 和 172.16.16.139 之间的完整区域传输示例。刚开始查看这个文件时,你可能会怀疑自己是否打开了正确的文件,因为你看到的是 TCP 数据包,而不是 UDP 数据包。虽然 DNS 依赖于 UDP,但在某些任务中,它使用 TCP,比如区域传输,因为 TCP 在传输大量数据时更为可靠。此捕获文件中的前三个数据包是 TCP 三次握手过程。
第四个数据包开始了 172.16.16.164 与 172.16.16.139 之间的区域传输请求。这个数据包不包含任何 DNS 信息。它被标记为“重新组装的 PDU 的 TCP 段”,因为区域传输请求数据包中的数据是通过多个数据包发送的。数据包 4 和 6 包含该数据包的数据,数据包 5 是确认数据包 4 已接收。这些数据包以这种方式显示,是因为 Wireshark 解析并显示 TCP 数据包的方式,使其更易于阅读。为了我们的目的,我们可以将数据包 6 作为完整的 DNS 区域传输请求,见图 9-20。

图 9-20:DNS 完整区域传输请求
区域传输请求是一个标准查询➊,但它请求的是 AXFR 类型➋,这意味着它希望从服务器接收整个 DNS 区域。服务器在数据包 7 中响应区域记录,如图 9-21 所示。如你所见,区域传输包含了相当多的数据,这只是其中一个简单的示例!随着区域传输完成,捕获文件以 TCP 连接拆除过程结束。
警告
区域传输中包含的数据在不当的人手中可能非常危险。例如,通过枚举单一的 DNS 服务器,你可以绘制出一个网络的完整基础设施。

图 9-21:发生 DNS 完整区域传输的过程
超文本传输协议 (HTTP)
超文本传输协议是万维网的传输机制,允许网页浏览器连接到网页服务器以查看网页。在大多数组织中,HTTP 代表了通过网络传输的流量中占比最高的部分。每次你进行 Google 搜索、发送推文或查看肯塔基大学篮球比分时,你都在使用 HTTP,例如访问www.espn.com/。
我们不会深入研究 HTTP 传输的数据包结构,因为 HTTP 协议有许多不同的实现方式,结构可能会有很大差异。因此,这部分练习留给你自己完成。在这里,我们将重点讨论一些 HTTP 的实际应用,例如检索和发布内容。
使用 HTTP 浏览
http_google.pcapng
HTTP 最常用于使用浏览器浏览网页。在捕获文件http_google.pcapng中,展示了一个使用 TCP 作为传输层协议的 HTTP 传输。通信从客户端 172.16.16.128 与 Google 网页服务器 74.125.95.104 之间的三次握手开始。
一旦建立通信,第一个数据包被标记为从客户端到服务器的 HTTP 数据包,如图 9-22 所示。

图 9-22:初始 HTTP GET请求数据包
HTTP 数据包通过 TCP 传输到服务器的端口 80➊,这是 HTTP 通信的标准端口(此外还经常使用其他端口,如 8080 和 8888)。
HTTP 数据包通过 HTTP 规范版本 1.1 中定义的八种请求方法之一来标识(见 www.iana.org/assignments/http-methods/http-methods.xhtml),这些方法指示数据包的发送者将对接收者执行的操作。如图 9-22 所示,该数据包将其方法标识为GET,其请求统一资源标识符(URI)为/,请求版本为HTTP/1.1 ➋。这些信息告诉我们,客户端正在发送请求以下载(GET)Web 服务器的根目录(/),并使用 HTTP 的 1.1 版本。
接下来,主机将有关其自身的信息发送到 Web 服务器。这些信息包括正在使用的浏览器(User-Agent)、浏览器接受的语言(Accept-Languages)以及 cookie 信息(捕获的底部)。服务器可以利用这些信息确定返回给客户端的数据,以确保兼容性。
当服务器收到第 4 个数据包中的 HTTP GET请求时,它会回应一个 TCP ACK,确认该数据包,并开始从第 6 到第 11 个数据包传输请求的数据。HTTP 仅用于在客户端和服务器之间发出应用层命令。为什么这些 HTTP 数据包在数据包列表中的协议标题下显示为 TCP?当数据传输开始时,Wireshark 数据包列表窗口将这些数据包标识为 TCP,而不是 HTTP,因为这些单独的数据包中没有 HTTP 请求/响应头。因此,在数据传输发生的地方,你会看到协议列显示为 TCP,而不是 HTTP。不过,这仍然是 HTTP 通信过程的一部分。
数据从服务器通过第 6 和第 7 个数据包发送,从客户端通过第 8 个数据包进行确认,再通过第 9 和第 10 个数据包发送两个数据包,最后通过第 11 个数据包进行另一次确认,如图 9-23 所示。所有这些数据包在 Wireshark 中显示为 TCP 段,而不是 HTTP 数据包,尽管 HTTP 仍然负责它们的传输。

图 9-23:TCP 在客户端浏览器和 Web 服务器之间传输数据
一旦数据传输完成,Wireshark 会重新组装数据流以供查看,如图 9-24 所示。

图 9-24:最终 HTTP 数据包,响应代码为 200
注意
在许多情况下,你在浏览数据包列表时无法看到可读的 HTML 数据,因为这些数据经过 gzip 压缩以提高带宽效率。这可以通过 Web 服务器返回的 HTTP 响应中的 Content-Encoding 字段来表示。只有当你查看完整流时,数据才会被解码并变得易于阅读。
HTTP 使用许多预定义的响应代码来指示请求方法的结果。在这个例子中,我们看到一个状态码为 200 ➊的数据包,表示请求方法成功。该数据包还包含了一个时间戳以及一些关于内容编码和 Web 服务器配置参数的附加信息。当客户端收到这个数据包时,交易就完成了。
使用 HTTP 发送数据
http_post.pcapng
现在我们已经查看了从 Web 服务器下载数据的过程,接下来让我们关注上传数据。文件http_post.pcapng包含了一个非常简单的上传示例:一个用户向网站发布评论。在初始的三次握手之后,客户端(172.16.16.128)发送一个 HTTP 数据包到 Web 服务器(69.163.176.56),如图 9-25 所示。

图 9-25:HTTP POST数据包
这个数据包使用POST方法 ➊将数据上传到 Web 服务器进行处理。这里使用的POST方法指定了 URI/wp-comments-post.php ➋以及 HTTP 版本HTTP/1.1。要查看发布的数据内容,请展开数据包中的 HTML 表单 URL 编码部分 ➌。
一旦数据通过这个POST传输,便会发送一个 ACK 数据包。如图 9-26 所示,服务器通过数据包 6 响应,传送响应代码 302 ➊,表示“找到”。

图 9-26:HTTP 响应 302 用于重定向。
302 响应代码是 HTTP 世界中常用的重定向方式。这个数据包中的 Location 字段指定了客户端应该被重定向到的位置 ➋。在这种情况下,位置是在发布评论的源网页上。客户端会执行一个新的GET请求,以获取新位置的内容,并通过接下来的几个数据包发送。最后,服务器传输状态码 200,通信结束。
简单邮件传输协议(SMTP)
如果说网页浏览是用户最常参与的活动,那么发送和接收电子邮件大概排在第二位。简单邮件传输协议(SMTP),用于 Microsoft Exchange 和 Postfix 等平台,是发送电子邮件的标准协议。
与 HTTP 类似,SMTP 数据包的结构可能会根据实现和客户端、服务器支持的功能集有所不同。在这一节中,我们将通过查看电子邮件发送过程的数据包级别内容来回顾 SMTP 的一些基本功能。
发送和接收电子邮件
支持电子邮件的架构类似于美国邮政服务。当你写信时,你把信放进邮箱,邮递员把信件取走并送到邮局进行分类。然后,信件要么被送到由同一个邮局服务的另一个邮箱,要么被送到另一个邮局,后者负责将其递送到目的地。信件可能会经过多个邮局,甚至是专门用于分发到特定地理区域的“中转”邮局。这个信息流在图 9-27 中有所展示。

图 9-27:通过邮政服务发送信件
发送电子邮件的方式非常类似,但术语有所不同。在个人用户层面,物理邮箱被一个数字邮箱所取代,数字邮箱负责存储和促进电子邮件的发送和接收。你通过邮件用户代理(MUA)来访问这个邮箱,MUA 是像微软 Outlook 或 Mozilla Thunderbird 这样的电子邮件客户端。
当你发送一条消息时,它会从你的 MUA 发送到邮件传输代理(MTA)。MTA 通常被称为邮件服务器,常见的邮件服务器应用程序有微软 Exchange 或 Postfix。如果发送的电子邮件目的地是来自同一域,那么 MTA 可以在无需进一步通信的情况下将其与收件人的邮箱关联。如果电子邮件要发送到另一个域,MTA 必须使用 DNS 来找到收件人邮件服务器的位置地址,然后将消息传输到该服务器。值得注意的是,邮件服务器通常由其他组件组成,如邮件投递代理(MDA)或邮件提交代理(MSA),但从网络角度来看,我们通常只关心客户端和服务器的概念。这个基本概述在图 9-28 中有所说明。

图 9-28:通过 SMTP 发送电子邮件
为了简化,我们将 MUA 称为电子邮件客户端,将 MTA 称为电子邮件服务器。
跟踪电子邮件消息
通过基本了解电子邮件消息的传输方式,我们可以开始查看表示这个过程的数据包。让我们从图 9-29 中的场景开始。

图 9-29:从发件人到收件人跟踪电子邮件
这个场景包含三个步骤:
-
用户从工作站(172.16.16.225)发送消息。电子邮件客户端通过 SMTP 将消息传输到本地邮件服务器(172.16.16.221 / skynet.local 域)。
-
本地邮件服务器接收消息,并通过 SMTP 将其传输到远程邮件服务器(172.16.16.231 / cyberdyne.local 域)。
-
远程邮件服务器接收消息,并将其与适当的邮箱关联。用户工作站上的电子邮件客户端(172.16.16.235)使用 IMAP 协议检索此消息。
步骤 1:客户端到本地服务器
mail_sender_client_1.pcapng
我们将通过查看步骤 1 来开始这个过程,这一步由mail_sender_client_1.pcapng表示。文件在用户点击其邮件客户端中的发送按钮时开始,启动了工作站与本地邮件服务器之间的数据包 1 到数据包 3 的 TCP 握手。
注意
在分析本节中的数据包捕获时,您可以忽略任何观察到的ETHERNET FRAME CHECK SEQUENCE INCORRECT错误。这些错误是实验环境中的副作用。
一旦建立连接,SMTP 协议接管并开始将用户的消息传输到服务器。您可以通过逐个滚动数据包并查看数据包详情窗口中的 SMTP 部分来检查每个 SMTP 请求和响应,但有更简单的方法。由于 SMTP 是一个简单的事务协议,并且我们的示例是明文传输,您可以通过跟踪 TCP 流来在一个窗口中查看整个事务。右键点击数据包中的任何一个,选择跟踪 ▶ TCP 流。生成的流在图 9-30 中显示。
连接建立后,邮件服务器在数据包 4 中向客户端发送服务横幅,表示它准备好接收命令。在此情况下,它自我标识为运行在 Ubuntu Linux 操作系统上的 Postfix 服务器 ➊。它还标识了它能够接收扩展 SMTP(ESMTP)命令。ESMTP 是 SMTP 规范的扩展,允许在邮件传输过程中使用额外的命令。
邮件客户端通过在数据包 5 中发出EHLO命令来做出响应 ➋。EHLO是“Hello”命令,用于在支持 ESMTP 时识别发送主机。如果 ESMTP 不可用,客户端将回退到HELO命令来标识自己。在本例中,发送方通过其 IP 地址进行标识,尽管也可以使用 DNS 名称。
在数据包 7 中,服务器响应包含包括VRFY、STARTTLS和SIZE 10240000 ➌等项的列表。这个列表反映了 SMTP 服务器支持的命令,提供给客户端,以便客户端知道在传输消息时可以使用哪些命令。每次 SMTP 事务开始时,在发送消息之前,都会进行此功能协商。消息的传输从数据包 8 开始,占据了本次捕获的大部分内容。

图 9-30:查看从邮件客户端到本地服务器的 TCP 流
SMTP 由客户端发送的简单命令和参数值控制,之后是服务器返回的响应代码。这与 HTTP 和 TELNET 等协议非常相似,且设计简洁。一个示例请求和响应可以在数据包 8 和 9 中看到,客户端发出MAIL命令,并带有参数FROM:<sanders@skynet.local> SIZE=556 ➍,服务器以响应代码 250(请求的邮件操作正常,已完成)和2.1.0 Ok参数做出响应。在这里,客户端识别了发件人的电子邮件地址和消息的大小,服务器则响应说已接收到这些数据并且是可接受的。在数据包 10 和 11 中会发生类似的交易,客户端发出RCPT命令,并带有参数TO:<sanders@cyberdyne.local> ➎,服务器则回应另一个250 2.1.5 Ok代码。
注意
如果你想查看所有可用的 SMTP 命令和参数,可以在这里查看: www.iana.org/assignments/mail-parameters/mail-parameters.xhtml。如果你想查看可用的响应代码,也可以在这里查看: www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.xml。
剩下的就是传输邮件内容本身了。客户端在数据包 12 中发出DATA命令,启动这个过程。服务器以代码 354 和一条信息 ➏回应,表示服务器已为消息创建了一个缓冲区,并告诉客户端开始传输。包含代码 354 的那一行告诉客户端,发送一个点(<CR><LF>.<CR><LF>)来标记传输的结束。消息以明文形式传输,且成功传输后,服务器发送响应代码。你会注意到,消息文本中还包含了一些附加信息,包括日期、内容类型和编码,以及与该传输相关的用户代理。这表明发送此消息的最终用户使用的是 Mozilla Thunderbird ➐。
传输完成后,SMTP 连接由邮件客户端通过在数据包 18 中发出没有参数的QUIT命令终止。服务器在数据包 19 中以响应代码 221(2.0.0 Bye参数 ➑作出回应。TCP 连接在数据包 20–23 中优雅地断开。
步骤 2:本地服务器到远程服务器
mail_sender_server_2.pcapng
接下来,我们将从负责skynet.local域的本地邮件服务器的角度来审视同样的场景;其地址是 172.16.16.221\。这个捕获文件可以在 mail_sender_server_2.pcapng 中找到,该文件直接从邮件服务器捕获。正如你所预期的,前 20 个左右的数据包与步骤 1 中的捕获镜像相同,因为它们是从另一个来源捕获的相同数据包。
如果发送的消息是发送到skynet.local域的另一个邮箱,我们就不会看到更多的 SMTP 流量;相反,我们会看到使用 POP3 或 IMAP 协议从邮件客户端检索消息。然而,由于此消息是发送到cyberdyne.local域,本地 SMTP 服务器必须将消息传输到负责该域的远程 SMTP 服务器。这个过程从数据包 22 开始,涉及本地服务器 172.16.16.221 和远程邮件服务器 172.16.16.231 之间的 TCP 握手。
注意
在实际场景中,邮件服务器通过使用一种称为邮件交换(MX)记录的特殊 DNS 记录类型来定位另一个服务器。由于这个场景是在实验室中创建的,且远程邮件服务器的 IP 地址已预配置在本地服务器上,因此我们不会在此看到该流量。如果你在排查邮件传输问题时,应考虑 DNS 问题与邮件协议问题的可能性。
建立连接后,我们可以在数据包列表窗口中看到,SMTP 被用来将消息发送到远程服务器。你可以通过查看此次事务的 TCP 流来更好地查看这个过程。它在图 9-31 中显示。如果你需要帮助来隔离这个连接,可以在过滤栏中应用过滤器 tcp.stream == 1。

图 9-31:查看从本地邮件服务器到远程邮件服务器的 TCP 流
这个事务与图 9-30 中的几乎相同。本质上,消息只是通过服务器之间传输。远程服务器将自己标识为mail02 ➊,本地服务器将自己标识为mail01 ➋,共享一组支持命令 ➌,并且消息在传输时完整无缺,其中之前事务的部分数据被附加到消息的收件人行(To line)上 ➍。这一切发生在数据包 27 到 35 之间,最后通过 TCP 拆除关闭了通信通道。
服务器最终并不关心消息是来自电子邮件客户端还是另一台 SMTP 服务器,因此所有相同的规则和程序都适用(除非有任何访问控制限制)。在现实世界中,本地邮件服务器和远程邮件服务器可能不支持相同的功能集,或者可能基于完全不同的平台。这就是为什么最初的 SMTP 通信如此重要的原因;它允许接收服务器将其支持的功能集传输给发送方。当一个 SMTP 客户端或服务器知道接收服务器支持的功能时,SMTP 命令可以进行调整,以便有效地传输消息。这种能力使得 SMTP 可以在任何数量的客户端和服务器技术之间广泛使用,这也是你在发送电子邮件时不必了解接收方的网络基础设施的原因。
步骤 3:远程服务器到远程客户端
mail_receiver_server_3.pcapng
此时,我们的消息已经到达了负责将电子邮件投递到 cyberdyne.local 域邮箱的远程服务器。接下来,我们将查看从远程服务器角度捕获的一个数据包,它的名称是 mail_receiver_server_3.pcapng,如 图 9-32 所示。

图 9-32:查看从本地邮件服务器到远程邮件服务器的 TCP 流
再次提醒,这次捕获中的前 15 个数据包看起来非常熟悉,因为它们代表的是相同的消息交换,其中源地址代表本地邮件服务器 ➊,目标地址代表远程邮件服务器 ➋。完成此序列后,SMTP 服务器可以将消息与适当的邮箱关联起来,以便目标接收者可以通过他们的电子邮件客户端检索消息。
如前所述,SMTP 主要用于发送电子邮件,并且迄今为止是最常见的用于该目的的协议。从服务器上的邮箱中检索电子邮件则相对更加开放,因为在这个过程中有不同的需求,因此有几种协议被设计来支持这个任务。最常见的协议是邮局协议版本 3(POP3)和互联网邮件访问协议(IMAP)。在我们的例子中,远程客户端通过 IMAP 协议在数据包 16 到 34 中从邮件服务器检索消息。
本书中我们不讨论 IMAP,但在这个例子中,即使我们讨论了它,它也不会给你太多帮助,因为通信是加密的。如果你查看数据包 21,你会看到客户端(172.16.16.235)在数据包 21 中向邮件服务器(172.16.16.231)发送了 STARTTLS 命令 ➊,如 图 9-33 所示。

图 9-33:STARTTLS 命令表示 IMAP 流量将被加密。
该命令告知服务器客户端希望使用 TLS 加密安全地检索邮件。在数据包 24–27 ➋ 中,客户端和服务器之间会协商出一个安全通道,随后邮件通过 TLS(传输层安全) 协议在剩余数据包 ➌ 中安全地被检索。如果你点击这些数据包查看数据或尝试跟踪 TCP 流(图 9-34),你会发现内容是不可读的,这样就能保护电子邮件不被可能试图恶意劫持或嗅探流量的人员截取。
随着最后的数据包接收完成,从一个域的用户向另一个域的用户发送邮件的过程就完成了。

图 9-34:IMAP 流量在客户端下载邮件时被加密。
通过 SMTP 发送附件
mail_sender_attachment.pcapng
SMTP 从来不是用来传输文件的机制,但由于通过电子邮件发送文件的便利性,它已经成为许多人主要的共享机制。让我们通过一个简单的例子,看看使用 SMTP 发送文件在数据包层面上是如何进行的。
在数据包捕获文件 mail_sender_attachment.pcapng 中,用户正在从其客户端(172.16.16.225)通过本地 SMTP 邮件服务器(172.16.16.221)向同一网络中的另一用户发送电子邮件。邮件包含一些文本,并附带一个图片文件。
通过 SMTP 发送附件与发送文本并没有太大区别。对于服务器来说,这些都只是数据,虽然通常会进行一些特殊编码,但我们仍然依赖 DATA 命令将数据传送到目的地。要看到这一过程的实际操作,打开捕获文件并跟踪给定 SMTP 事务的 TCP 流。这一过程在 图 9-35 中有所展示。

图 9-35:用户通过 SMTP 发送附件
这个例子和之前的场景一样,首先是服务识别和支持协议的交换。当客户端准备好发送邮件时,它会提供发件人和收件人的地址,并发送 DATA 命令,指示服务器打开一个缓冲区来接收信息。此时,事情就有些不同了。
在前面的示例中,客户端直接将文本传输到服务器,仅此而已。在这个示例中,客户端必须同时发送明文消息和与图像附件相关的二进制数据。为了实现这一点,它将其 Content-Type 标识为multipart/mixed,并使用边界值------------050407080301000500070000 ➊。这告诉服务器,正在传输多种类型的数据,每种数据都有自己独特的 MIME 类型和编码,并且每种数据将通过指定的边界值进行分隔。因此,当另一个邮件客户端接收到这些数据时,它将根据边界值以及每个数据块中指定的唯一 MIME 类型和编码来解释数据。
在我们的示例中,这条消息有两个独特的部分。第一个是邮件正文本身,它通过内容类型text/plain ➋进行标识。接下来,我们看到一个边界标记和新消息部分的开始 ➌。这一部分包含图像文件,并通过内容类型image/jpeg ➍进行标识。还值得注意的是,Content-Transfer-Encoding的值被设置为base64 ➎,这意味着数据必须从 Base64 编码转换才能进行解析。剩余的传输内容包括编码后的图像文件 ➏。
无论你做什么,都不要把这种编码与安全功能混淆。Base64 编码几乎是瞬时可逆的,任何拦截此通信的攻击者都能轻松恢复图像文件。如果你有兴趣自己从数据包捕获中提取出这个图像文件,在第十二章的远程访问木马部分有一个类似的场景,我们在那里从基于 HTTP 的文件传输中提取图像。阅读完后,翻回这个捕获文件,看看你是否能找出用户神秘的新同事是谁。
最终思考
本章介绍了在分析应用层流量时最常遇到的协议。在接下来的章节中,我们将探讨新的协议以及我们在此处讨论的协议的附加功能,同时探索各种真实世界的场景。
要了解更多关于各个协议的信息,请阅读它们相关的 RFC,或参考 Charles M. Kozierok 所著的《TCP/IP 指南》(No Starch Press,2005)。此外,请参阅附录 A 中的资源列表。
第十章:基础现实世界场景

从这一章开始,我们将深入数据包分析的核心内容,使用 Wireshark 分析现实世界中的网络问题。我将通过描述问题的背景并提供分析师当时获得的信息来介绍一系列问题场景。在打下基础后,我们将转向分析部分,我会描述用于捕获适当数据包的方法,并引导你一步步向诊断迈进。一旦分析完成,我将指出潜在的解决方案并概述学到的经验教训。
在整个过程中,请记住,分析是一个非常动态的过程。因此,我用来分析每个场景的方法可能和你使用的方法不同。每个人通过自己的视角来解决问题和推理。最重要的是,分析的结果能解决问题,即使没有解决问题,从失败中学习也是至关重要的。毕竟,经验是我们在没有得到想要的结果时获得的。
此外,本章讨论的大多数问题可能通过不一定需要使用数据包嗅探器的方法来解决,但那样有什么趣味呢?当我第一次学习如何分析数据包时,我发现通过使用数据包分析技巧以不寻常的方式分析典型问题很有帮助,这也是我向你们展示这些场景的原因。
缺失的网页内容
http_espn_fail.pcapng
在我们要查看的第一个场景中,我们的用户是数据包皮特,他是一个大学篮球迷,不熬夜,通常错过西海岸的比赛。每当他早上坐到工作站时,他首先做的事就是访问www.espn.com/查看前一晚的比赛最终得分。当皮特今天早上浏览 ESPN 时,他发现页面加载非常缓慢,最终加载完成时,大部分图片和内容都缺失了(图 10-1)。让我们帮皮特诊断这个问题。

图 10-1:ESPN 加载不正常
连接到线路
这个问题仅限于皮特的工作站,并没有影响到其他工作站,所以我们将从皮特的工作站直接捕获数据包来开始。为此,我们将安装 Wireshark 并在浏览 ESPN 网站时捕获数据包。这些数据包存储在文件http_espn_fail.pcapng中。
分析
我们知道 Pete 的问题是他无法查看他正在浏览的网站,因此我们主要会查看 HTTP 协议。如果你阅读了上一章,你应该对客户端和服务器之间的 HTTP 流量有一个基本的了解。一个好的起点是查看向远程服务器发出的 HTTP 请求。你可以通过应用GET请求的过滤器(使用 http.request.method == "GET")来做到这一点,但也可以通过从主下拉菜单中选择统计信息 ▶ HTTP ▶ 请求来实现这一点(图 10-2)。

图 10-2:查看向 ESPN 发送的 HTTP 请求
从这个概述中看,捕获内容似乎仅限于七个不同的 HTTP 请求,而且它们看起来都与 ESPN 网站相关。每个请求的域名中都包含espn这个字符串,唯一例外的是 cdn.optimizely.com,它是一个内容分发网络(CDN),用于向多个网站投放广告。浏览到托管广告或其他外部内容的网站时,看到对各种 CDN 的请求是很常见的。
由于没有明确的线索可供追踪,下一步是通过选择统计信息 ▶ 协议层级来查看捕获文件的协议层级。这将帮助我们发现意外的协议或每种协议的流量分布情况(图 10-3)。请记住,协议层级屏幕基于当前应用的显示过滤器。请确保清除先前应用的过滤器,以便基于整个数据包捕获获得预期结果。

图 10-3:查看浏览会话的协议层级
协议层级并不复杂,我们可以迅速解读出只有两个应用层协议在工作:HTTP 和 DNS。正如你在第九章中所学,DNS 用于将域名转换为 IP 地址。因此,当你浏览像 www.espn.com/ 这样的网站时,如果系统尚未知道远程服务器的 IP 地址,可能需要发送 DNS 查询来查找该 IP 地址。一旦收到包含适当 IP 地址的 DNS 回复,该信息可以被添加到本地缓存中,然后可以开始进行 HTTP 通信(使用 TCP)。
虽然这里看起来并没有什么异常,但 14 个 DNS 数据包是值得注意的。一个域名的 DNS 请求通常会包含在一个数据包中,响应也会构成一个数据包(除非数据包非常大,在这种情况下 DNS 会使用 TCP)。由于这里有 14 个 DNS 数据包,可能生成了多达七个 DNS 查询(7 个查询 + 7 个回复 = 14 个数据包)。图 10-2 确实显示了对七个不同域名的 HTTP 请求,但 Pete 在浏览器中只输入了一个 URL。为什么会发出这么多额外的请求呢?
在一个简单的世界里,访问一个网页可能就像查询一个服务器并通过一次 HTTP 对话拉取所有内容一样简单。实际上,单个网页可能会提供托管在多个服务器上的内容。所有基于文本的内容可能在一个地方,图形可能在另一个地方,嵌入的视频可能在第三个地方。除此之外,还有广告,这些广告可能由多个提供商托管,跨越数十个独立的服务器。每当 HTTP 客户端解析 HTML 代码并找到引用其他主机内容的链接时,它会尝试查询该主机以获取内容,这就可能生成额外的 DNS 查询和 HTTP 请求。这正是 Pete 访问 ESPN 时发生的情况。尽管他可能只打算查看来自单一来源的内容,但在 HTML 代码中找到了对其他内容的引用,他的浏览器自动向多个不同的域名请求这些内容。
现在我们已经理解了所有这些额外请求的存在原因,接下来的步骤是检查与每个请求相关的个别对话(统计 ▶ 对话)。查看对话窗口(图 10-4)提供了一个重要线索。

图 10-4:审查 IP 对话
我们之前发现有七个 DNS 请求和七个 HTTP 请求相匹配。考虑到这一点,合理的预期是会有七个匹配的 IP 对话,但事实并非如此。实际上有八个。那该如何解释呢?
一个可能的想法是,捕获的数据中可能有与当前问题无关的额外对话“污染”了分析结果。确保分析不受无关流量的影响是非常重要的,但这并不是本次对话中的问题。如果你检查每个 HTTP 请求并记录请求发送的 IP 地址,你应该会发现有一个对话没有匹配的 HTTP 请求。这个对话的终端是 Pete 的工作站(172.16.16.154)和远程 IP(203.0.113.94)。这个对话在图 10-4 的底部表示。我们注意到,6,774 字节被发送到这个未知主机,但没有字节被返回:这值得进一步探究。
如果你对这个对话进行过滤(右键点击该对话并选择应用为过滤器 ▶ 选择 ▶ A<->B),你可以运用你对 TCP 的知识来识别出了什么问题(图 10-5)。

图 10-5:回顾意外连接
在正常的 TCP 通信中,你会看到标准的 SYNSYN/ACK-ACK 握手序列。在这种情况下,Pete 的工作站向 203.0.113.94 发送了一个 SYN 数据包,但我们从未看到 SYN/ACK 响应。不仅如此,Pete 的工作站多次发送 SYN 数据包也未能成功,最终导致他的计算机发送 TCP 重传数据包。我们将在第十一章中详细讨论 TCP 重传的具体情况,但这里的关键要点是,一个主机发送了数据包,却没有收到任何响应。从时间列中可以看到,重传持续了 95 秒而没有得到响应。在网络通信中,这比蜂蜜还慢。
我们已经识别出七个 DNS 请求、七个 HTTP 请求和八个 IP 对话。由于我们知道捕获的数据没有被额外数据污染,因此可以合理推测神秘的第八个 IP 对话可能是 Pete 的网页加载缓慢且不完全的原因。由于某种原因,Pete 的工作站正在尝试与一个不存在或根本没有响应的设备进行通信。为了理解为什么会发生这种情况,我们不去查看捕获文件中的内容,而是考虑文件中缺失的部分。
当 Pete 浏览到 www.espn.com/ 时,他的浏览器识别出了托管在其他域名上的资源。为了检索这些数据,他的工作站生成了 DNS 请求来查找它们的 IP 地址,然后通过 TCP 连接到这些地址,以便发送 HTTP 请求获取内容。在与 203.0.113.94 的对话中,并没有找到 DNS 请求。那么,Pete 的工作站是如何知道这个地址的呢?
如果你还记得我们在第九章中讨论的 DNS 内容,或者你对 DNS 有一定了解,你就知道大多数系统都实现了某种形式的 DNS 缓存。这使得它们可以引用已经检索到的本地 DNS 到 IP 地址的映射,而无需每次访问一个常用域名时都生成 DNS 请求。最终,这些 DNS 到 IP 的映射会过期,必须生成新的请求。然而,如果 DNS 到 IP 的映射发生了变化,而设备在下次访问时没有生成 DNS 请求来获取新的地址,那么该设备将尝试连接一个已经失效的地址。
在皮特的情况下,正是发生了这种情况。皮特的工作站已经缓存了一个 DNS 到 IP 的映射,该映射指向托管 ESPN 内容的域名。由于这个缓存条目存在,DNS 请求没有被生成,他的系统尝试直接连接到旧的地址。然而,那个地址已经不再配置为响应请求。因此,请求超时,内容也没有加载出来。
幸运的是,对于皮特来说,手动清除 DNS 缓存只需要在命令行或终端窗口中敲几下键就能完成。或者,他也可以等几分钟,等 DNS 缓存条目过期时,再尝试一次,这时会生成一个新的请求。
经验教训
这是一项大工程,目的只是为了知道肯塔基大学以 90 分的优势击败了杜克大学,但我们却从中获得了对网络主机关系更深的理解。在这个场景中,我们通过评估与请求和通信相关的多个数据点,逐步找到了问题的解决办法。通过这些数据点,我们发现了一些不一致之处,进而发现了客户端与 ESPN 内容分发服务器之间的通信故障。
在现实世界中,诊断问题很少像滚动查看数据包列表并寻找看起来奇怪的数据包那么简单。即便是最简单的问题,排除故障也可能导致非常大的抓包文件,这时就需要依赖 Wireshark 的分析和统计功能来识别异常。熟悉这种分析方式对于在数据包级别上成功排查故障至关重要。
如果你想看看正常的 web 浏览器与 ESPN 之间的通信示例,试着自己访问该网站并捕获流量,看看你能否识别出所有负责传递内容的服务器。
无响应的天气服务
weather_broken.pcapng weather_working.pcapng
我们的第二个场景再次涉及到我们的朋友数据包皮特。在他众多的爱好中,皮特自认为是一个业余气象学家,几乎每隔几个小时就会检查当前的天气状况和预报。不过,他并不完全依赖当地新闻的天气预报;他实际上在家外面安装了一个小型气象站,将数据报告上传到* www.wunderground.com/*,以便聚合和查看。今天,皮特去检查他的气象站,看看气温一夜之间下降了多少,但发现他的气象站已经超过九个小时没有向 Wunderground 报告数据了,从大约午夜开始(图 10-6)。

图 10-6:气象站已经九小时没有报告数据了。
深入了解数据线
在 Pete 的网络中,安装在他屋顶上的气象站通过 RF 连接与屋内的接收器相连。接收器连接到他的网络交换机,并通过互联网向 Wunderground 报告统计数据。这种架构在图 10-7 中进行了示意。

图 10-7:气象站网络架构
接收器有一个简单的基于网页的管理页面,但 Pete 登录后只看到一条关于最后一次同步时间的晦涩信息,并没有提供任何额外的故障排除指导——软件没有提供详细的错误日志。由于接收器是气象站基础设施的通信枢纽,捕获传入和传出的数据包来诊断问题是有意义的。这是一个家庭网络,所以在 SOHO 交换机上可能没有端口镜像功能。我们最好的选择是使用便宜的 taps,或者执行 ARP 缓存中毒来拦截这些数据包。捕获的数据包存储在文件weather_broken.pcapng中。
分析
打开捕获文件后,你会发现我们再次处理的是 HTTP 通信。数据包捕获仅限于 Pete 本地气象接收器 172.16.16.154 与互联网中一个未知远程设备 38.102.136.125 之间的单一对话(见图 10-8)。

图 10-8:隔离的气象站接收器通信
在我们检查对话的特征之前,先看看能否识别出这个未知 IP。在没有广泛研究的情况下,我们可能无法确定这个 IP 是否是 Pete 的气象接收器应该连接的确切 IP 地址,但我们至少可以通过进行 WHOIS 查询验证它是否属于 Wunderground 的基础设施。你可以通过大多数域名注册或区域互联网注册网站进行 WHOIS 查询,例如whois.arin.net/。在这种情况下,看起来该 IP 属于 Cogent,一家互联网服务提供商(ISP)(见图 10-9)。PSINet Inc.也在这里提到,但通过快速搜索发现,PSINet 的大多数资产在 2000 年代初被 Cogent 收购。

图 10-9:WHOIS 数据识别了该 IP 的所有者。
在某些情况下,如果一个 IP 地址直接注册到某个组织,WHOIS 查询会返回该组织的名称。然而,很多时候公司只是利用互联网服务提供商(ISP)的 IP 地址空间,而没有将其直接注册到自己名下。在这些情况下,另一个有用的策略是搜索与 IP 地址相关联的 自治系统号码(ASN)。组织需要注册 ASN 以支持公共互联网中的某些类型路由。有多种方式可以查找 IP 到 ASN 的关联(一些 WHOIS 查询会自动提供),但我喜欢使用 Team Cymru 的自动查找工具 (asn.cymru.com/)。通过这个工具查询 38.102.136.125,我们看到它与 AS 36347 相关联,而 AS 36347 又与“Wunderground – The Weather Channel, LLC, US”相关联(图 10-10)。这告诉我们,天气站正在与设备进行通信,至少该设备在正确的网络环境中。如果我们无法识别该地址的正确归属,可能需要探索 Pete 的接收器是否与错误的设备通信,但该地址是正确的。

图 10-10:外部 IP 地址的 IP 到 ASN 查找
在明确了未知主机之后,我们可以深入研究通信的细节。整个通信过程相对简短。它包括一次 TCP 握手,一个 GET 请求和响应,以及一次 TCP 拆除。握手和拆除看起来是成功的,因此我们遇到的问题很可能仅限于 HTTP 请求本身。为了仔细检查这一点,我们将跟踪 TCP 流(图 10-11)。

图 10-11:跟踪天气接收器通信的 TCP 流
HTTP 通信从 Pete 的天气接收器向 Wunderground 发送的 GET 请求开始。没有传输 HTTP 内容,但在 URL ➊ 中传输了大量数据。通过 URL 查询字符串传输数据在 Web 应用中很常见,看来接收器正通过这种机制传递天气更新。例如,你可以看到字段如 tempf=43.0、dewptf=13.6 和 windchillf=43.0。Wunderground 的收集服务器正在从 URL 中解析字段和参数列表,并将它们存储在数据库中。
初看之下,向 Wunderground 服务器发送的 GET 请求似乎一切正常。但查看相应的回复时发现报告了一个错误。服务器响应了一个 HTTP/1.0 200 OK 响应代码 ➋,表示 GET 请求已接收并成功,但响应体中包含一条有用的消息:INVALIDPASSWORDID|密码或密钥和/或 ID 不正确 ➌。
如果你回过头看一下请求 URL,你会发现传递的前两个参数是ID和PASSWORD。这两个参数用于识别气象站的呼号并将其认证到 Wunderground 服务器。
在这种情况下,Pete 的气象站 ID 是正确的,但密码不正确。由于某种未知原因,它被替换成了零。由于上次已知的成功通信发生在午夜,因此有可能是应用了某次更新,或者接收器重启后丢失了密码配置。
注意
虽然许多开发人员选择在 URL 中传递参数,但通常不推荐像这里一样将密码放在 URL 中。因为在使用 HTTP 时,所请求的 URL 会以明文形式传输,除非添加了加密,例如 HTTPS。因此,任何一个恰巧监听网络的恶意用户都可能拦截你的密码。
在这一点上,Pete 能够访问他的接收器并输入新密码。没过多久,他的气象站开始重新同步数据。成功的气象站通信示例可以在 weather_working.pcapng 中找到。通信流如 图 10-12 所示。

图 10-12:成功的气象站通信
现在密码是正确的 ➊,Wunderground 服务器在 HTTP 响应体中返回了 success 消息 ➋。
经验教训
在这种情况下,我们遇到了一个第三方服务,通过使用另一种协议(HTTP)中可用的功能来促进网络通信。解决第三方服务的通信问题是你经常会遇到的事情,而当没有合适的文档或错误日志时,数据包分析技术非常适合用于排查这些服务的问题。随着物联网(IoT)设备的普及,如本示例中的气象站,这种情况变得越来越常见。
解决这些问题需要能够检查未知的流量序列,并推断出事物应该如何工作。一些应用程序,如本场景中的基于 HTTP 的气象数据传输,比较简单。而其他一些应用则相当复杂,可能涉及多个事务、添加加密,甚至是 Wireshark 无法原生解析的自定义协议。
当你调查更多第三方服务时,你最终会开始了解开发人员用来促进网络通信的常见模式。这些知识将提高你在排查问题时的效率。
无互联网访问
在许多情况下,你可能需要诊断和解决互联网连接问题。我们将讨论一些你可能遇到的常见问题。
网关配置问题
nowebaccess1.pcapng
我们的下一个场景呈现了一个常见问题:用户无法访问互联网。我们已确认用户可以访问网络的所有内部资源,包括其他工作站的共享资源和本地服务器上托管的应用程序。
网络架构非常简单,因为所有的客户端和服务器都连接到一系列简单的交换机。互联网接入通过一个路由器处理,该路由器作为默认网关,IP 地址信息由 DHCP 提供。这是小型办公室中非常常见的场景。
接入网络
为了确定问题的原因,我们可以让用户在我们监听网络时尝试浏览互联网。我们使用第二章中的信息(见图 2-15)来确定放置嗅探器的最合适方法。
我们网络中的交换机不支持端口镜像。我们已经需要中断用户以进行测试,因此我们可以假设再次将用户下线是可以的。即使这不是一个高吞吐量的场景,如果有 TAP 设备,使用它也是合适的。生成的文件是nowebaccess1.pcapng。
分析
流量捕获始于一个 ARP 请求和回复,如图 10-13 所示。在数据包 1 中,用户的计算机,MAC 地址为 00:25:b3:bf:91:ee,IP 地址为 172.16.0.8,向网络段上的所有计算机广播 ARP 数据包,试图找到与其默认网关的 IP 地址 172.16.0.10 相关联的 MAC 地址。

图 10-13:计算机默认网关的 ARP 请求和回复
在数据包 2 中接收到一个响应,用户的计算机得知 172.16.0.10 的 MAC 地址是 00:24:81:a1:f6:79。一旦接收到这个回复,计算机便有了通往网关的路由,网关应该能够将其引导到互联网。
在 ARP 回复之后,计算机必须尝试通过 DNS 解析网站的 DNS 名称为 IP 地址,在数据包 3 中完成。如图 10-14 所示,计算机通过向其主要 DNS 服务器 4.2.2.2 发送 DNS 查询数据包来执行此操作➊。

图 10-14:发送到 4.2.2.2 的 DNS 查询
在正常情况下,DNS 服务器会非常快速地响应 DNS 查询,但这里并非如此。我们没有收到响应,而是看到同样的 DNS 查询第二次发送到不同的目标地址。如图 10-15 所示,在数据包 4 中,第二个 DNS 查询被发送到计算机上配置的备用 DNS 服务器 4.2.2.1➊。

图 10-15:发送到 4.2.2.1 的第二个 DNS 查询
再次,由于没有收到 DNS 服务器的回复,查询在 1 秒后再次发送到 4.2.2.2。这个过程会重复进行,在接下来的几秒钟内,查询会在主 DNS 服务器➊和备用 DNS 服务器➋之间交替进行,如图 10-16 所示。整个过程大约需要 8 秒钟➌,或者直到用户的互联网浏览器报告无法访问网站。

图 10-16:DNS 查询会一直重复,直到通信停止。
根据我们看到的数据包,我们可以开始定位问题的根源。首先,我们看到一个成功的 ARP 请求,目标是我们认为是网络默认网关路由器的设备,所以我们知道该设备在线并且在通信。我们还知道用户的计算机实际上正在向网络发送数据包,因此可以假设计算机本身的协议栈没有问题。问题显然在 DNS 请求发出时发生。
在该网络中,DNS 查询由互联网上的外部服务器(4.2.2.2 或 4.2.2.1)解析。这意味着,要正确解析,负责将数据包路由到互联网的路由器必须成功地将 DNS 查询转发到服务器,并且服务器必须做出响应。在 HTTP 请求网页之前,这一切都必须先发生。
因为没有其他用户遇到连接互联网的问题,所以网络路由器和远程 DNS 服务器可能不是问题的根源。剩下需要调查的唯一问题就是用户的计算机本身。
在对受影响的计算机进行更深入检查后,我们发现计算机并没有收到由 DHCP 分配的地址,而是手动设置了地址信息,并且默认网关地址设置错误。设置为默认网关的地址不是路由器,无法将 DNS 查询数据包转发到网络外部。
经验教训
这个场景中的问题源于客户端配置错误。虽然问题本身很简单,但对用户的影响却很大。对于缺乏网络知识或无法进行快速数据包分析的人员来说,像这样一个简单的配置错误可能需要相当长的时间来排除,就像我们这里所做的那样。正如你所看到的,数据包分析并不限于大型复杂的问题。
请注意,由于我们在进入场景时并不知道网络网关路由器的 IP 地址,Wireshark 没有准确识别问题,但它确实告诉我们该往哪里找,节省了宝贵的时间。与其检查网关路由器、联系 ISP,或尝试找到资源来排除远程 DNS 服务器的问题,我们能够将故障排除的重点放在计算机本身,事实证明,问题的根源就在于此。
注意
如果我们对该特定网络的 IP 地址分配方案更为熟悉,分析可能会更加迅速。一旦我们发现 ARP 请求发送到了与网关路由器不同的 IP 地址,我们就能立即识别出问题。这类简单的配置错误通常是网络问题的根源,并且通过一些数据包分析通常可以迅速解决。
不需要的重定向
nowebaccess2.pcapng
在这种情况下,我们再次遇到一个用户,正在遇到无法从工作站访问互联网的问题。然而,与前一情形中的用户不同,这个用户能够访问互联网。他们的问题是无法访问主页,* www.google.com/*。当用户尝试访问任何由 Google 托管的域时,他们被引导到一个浏览器页面,显示“Internet Explorer 无法显示网页”。这个问题只影响这个特定的用户。
与之前的情况一样,这也是一个小型网络,拥有一些简单的交换机和一个作为默认网关的路由器。
接入网络
为了开始分析,我们让用户尝试访问www.google.com/,同时我们通过一个监听点来捕获生成的流量。结果生成的文件是nowebaccess2.pcapng。
分析
捕获开始时是一个 ARP 请求和回复,如图 10-17 所示。在数据包 1 中,用户的计算机,MAC 地址为 00:25:b3:bf:91:ee,IP 地址为 172.16.0.8,向网络段上的所有计算机广播 ARP 数据包,试图找到与主机 IP 地址 172.16.0.102 关联的 MAC 地址。我们暂时没有识别出这个地址。

图 10-17:网络上另一个设备的 ARP 请求和回复
在数据包 2 中,用户的计算机得知 IP 地址 172.16.0.102 对应的 MAC 地址是 00:21:70:c0:56:f0。基于之前的情形,我们可能会假设这是网关路由器的地址,并且该地址被用来转发数据包到外部 DNS 服务器。然而,如图 10-18 所示,接下来的数据包并不是 DNS 请求,而是从 172.16.0.8 到 172.16.0.102 的 TCP 数据包。它设置了 SYN 标志➌,表明这是两个主机之间建立新 TCP 连接的握手中的第一个数据包。

图 10-18:从一个内部主机发送到另一个主机的 TCP SYN 数据包
值得注意的是,TCP 连接尝试是向 172.16.0.102 ➊的端口 80 ➋发起的,该端口通常与 HTTP 流量相关。
如图 10-19 所示,当主机 172.16.0.102 发送一个 TCP 数据包(数据包 4)并设置了 RST 和 ACK 标志➊时,连接尝试被突然中断。

图 10-19:响应 TCP SYN 的 TCP RST 数据包
回想一下第八章,当 RST 标志位设置时,数据包用于终止 TCP 连接。在这里,IP 地址为 172.16.0.8 的主机尝试与 IP 地址为 172.16.0.102 的主机在 80 端口建立 TCP 连接。不幸的是,因为该主机没有配置监听 80 端口请求的服务,所以发送了 TCP RST 数据包来终止连接。此过程重复了三次,最终通信结束,正如在图 10-20 中所示。此时,用户在浏览器中收到一条消息,表示页面无法显示。

图 10-20:TCP SYN 和 RST 数据包共出现了三次。
在检查了另一台正常工作的网络设备的配置后,我们对数据包 1 和 2 中的 ARP 请求和回复感到担忧,因为 ARP 请求不是针对网关路由器的实际 MAC 地址,而是针对某个未知设备。紧接着 ARP 请求和回复,我们预计会看到一个 DNS 查询发送到我们配置的 DNS 服务器,以便查找与www.google.com/相关联的 IP 地址,但实际上没有。可能阻止 DNS 查询发生的两种情况是:
• 发起连接的设备已经在其 DNS 缓存中拥有 DNS 名称到 IP 地址的映射(如本章第一个场景所示)。
• 连接到 DNS 名称的设备已经在其hosts文件中指定了 DNS 名称到 IP 地址的映射。
进一步检查客户端计算机后,我们发现该计算机的hosts文件中有一条与内部 IP 地址 172.16.0.102 关联的www.google.com/条目。这个错误的条目是导致用户问题的根源。
计算机通常会将其hosts文件作为 DNS 名称到 IP 地址映射的权威来源,并且在查询外部源之前会检查该文件。在这个场景中,用户的计算机检查了其hosts文件,发现了与www.google.com/相关的条目,并决定www.google.com/实际上位于它自己的本地网络段。接下来,它发送了一个 ARP 请求到该主机,收到了响应,并尝试与 172.16.0.102 的 80 端口建立 TCP 连接。然而,由于远程系统未配置为 Web 服务器,它未能接受连接尝试。
一旦移除了hosts文件中的条目,用户的计算机开始正确地进行通信,并且能够访问www.google.com/。
注意
要检查 Windows 系统上的hosts文件,请打开C:\Windows\System32\drivers\etc\hosts。在 Linux 上,查看/etc/hosts*。
这种非常常见的情况是恶意软件多年来一直在使用的,用来将用户重定向到托管恶意代码的网站。试想,如果攻击者修改了你的hosts文件,让你每次进行网上银行操作时,都被重定向到一个旨在窃取账户凭证的假网站!
经验教训
当你继续分析流量时,你会了解到各种协议如何工作以及如何破坏它们。在这个场景中,DNS 查询没有发送,是因为客户端配置错误,而不是由于外部的限制或配置错误。
通过在数据包级别检查这个问题,我们能够迅速发现一个未知的 IP 地址,并确定通信过程中的关键组件 DNS 丢失。通过这些信息,我们能够将问题源归结为客户端。
上游问题
nowebaccess3.pcapng
与前两个场景类似,在这个场景中,用户抱怨工作站无法访问互联网。该用户已将问题缩小到一个网站,* www.google.com/*。进一步调查后,我们发现这个问题影响了组织中的所有人——没有人能够访问 Google 域名。
网络配置与之前的两个场景相同,只有一些简单的交换机和一台路由器将网络连接到互联网。
接入线路
为了解决这个问题,我们首先访问* www.google.com/* 来生成流量。由于这个问题是全网络范围的,理想情况下网络中的任何设备都应该能够通过大多数捕获方法重现这个问题。通过接入捕获得到的文件是 nowebaccess3.pcapng。
分析
这个数据包捕获从 DNS 流量开始,而不是我们习惯看到的 ARP 流量。因为捕获中的第一个数据包是发送到外部地址的,且数据包 2 包含来自该地址的回复,我们可以假设 ARP 过程已经完成,网关路由器的 MAC 到 IP 地址映射已经存在于主机的 ARP 缓存中,地址为 172.16.0.8。
如图 10-21 所示,捕获中的第一个数据包是从主机 172.16.0.8 发送到地址 4.2.2.1 ➊,这是一个 DNS 数据包 ➋。检查数据包的内容,我们看到这是一个查询* www.google.com*的 A 记录 ➌,用于将 DNS 名称映射到 IP 地址。

图 10-21: www.google.com 的 DNS 查询 A 记录
来自 4.2.2.1 的查询响应是捕获文件中的第二个数据包,如图 10-22 所示。在这里,我们看到响应这个请求的名称服务器为查询提供了多个答案 ➊。此时,一切看起来都正常,通信也按预期进行。

图 10-22:DNS 回复包含多个 A 记录
现在,用户的计算机已经确定了 Web 服务器的 IP 地址,它可以尝试与服务器进行通信。如图 10-23 所示,这一过程在数据包 3 中开始,TCP 数据包从 172.16.0.8 发送到 74.125.95.105 ➊。这个目标地址来自 DNS 查询响应中看到的第一个 A 记录,即数据包 2 中的内容。该 TCP 数据包的 SYN 标志被设置 ➋,并且它尝试与远程服务器在端口 80 上进行通信 ➌。

图 10-23:SYN 数据包正在尝试在端口 80 上发起连接。
因为这是一个 TCP 握手过程,我们知道应该会收到一个 TCP SYN/ACK 数据包作为响应,但实际上,在短暂的时间后,源主机再次向目标发送了另一个 SYN 数据包。大约一秒钟后,这一过程再次发生,如图 10-24 所示,随后通信停止,浏览器显示无法找到该网站。

图 10-24:尝试三次发送 TCP SYN 数据包,但没有收到响应。
在我们排查这个问题时,请考虑到,我们知道网络内的工作站能够连接到外部世界,因为向外部 DNS 服务器(4.2.2.1)的 DNS 查询成功。DNS 服务器响应了一个看起来有效的地址,我们的主机尝试连接这些地址之一。此外,我们试图连接的本地工作站似乎也是正常的。
问题在于远程服务器根本没有响应我们的连接请求;没有发送 TCP RST 数据包。这可能由多种原因引起:配置错误的 Web 服务器、Web 服务器上的协议栈损坏,或者远程网络中的数据包过滤设备(如防火墙)。假设没有本地的数据包过滤设备,所有其他潜在的解决方案都在远程网络上,超出了我们的控制范围。在这种情况下,Web 服务器无法正常工作,访问尝试均未成功。问题解决后,Google 端修复了问题,通信才得以继续。
经验教训
在这种情况下,问题并不是我们能解决的。我们的分析表明,问题不在于我们网络中的主机、我们的路由器,或者提供名称解析服务的外部 DNS 服务器。问题在我们的网络基础设施之外。
有时候,发现问题并非我们自己的问题,不仅能减轻压力,还能在管理层找上门时挽回面子。我曾与许多 ISP、供应商和软件公司发生过争执,他们声称问题不在他们,但正如你刚刚看到的,数据包是不会撒谎的。
不稳定的打印机
在下一个场景中,一位 IT 帮助台管理员正在解决打印问题。销售部门的用户报告称,高容量打印机出现故障。当用户将大打印任务发送到打印机时,打印机会打印几页,然后在任务完成前停止打印。虽然已经尝试了多次驱动程序配置更改,但都没有成功。帮助台工作人员希望你能确保这不是网络问题。
连接到数据线
inconsistent_printer.pcapng
这个问题的共同点是打印机,因此我们首先将嗅探器放置在尽可能靠近打印机的位置。虽然我们不能在打印机上安装 Wireshark,但该网络使用的是先进的 3 层交换机,因此我们可以使用端口镜像。我们将打印机使用的端口镜像到一个空闲端口,并将安装了 Wireshark 的笔记本电脑连接到该端口。一旦设置完成,我们将让用户向打印机发送大打印任务,以便我们监控输出。结果生成的捕获文件是 inconsistent_printer.pcapng。
分析
网络工作站(172.16.0.8)与打印机(172.16.0.253)之间的 TCP 握手开始时发起连接,并出现在捕获文件的开头。握手之后,一个 1,460 字节的 TCP 数据包 ➊ 被发送到打印机,出现在数据包 4 中(图 10-25)。数据的数量可以在包列表窗格的最右侧的“信息”列中或在包详细信息窗格的 TCP 头部信息的底部看到。

图 10-25:通过 TCP 向打印机传输的数据
在数据包 4 之后,又发送了一个数据包,包含 1,460 字节的数据 ➊,如图 10-26 所示。打印机在数据包 6 ➋ 中确认接收了这些数据。

图 10-26:正常的数据传输和 TCP 确认
数据流会一直持续,直到捕获到最后几包数据。数据包 121 是一个 TCP 重传数据包,这是一个问题的迹象,如图 10-27 所示。
当一个设备向远程设备发送 TCP 数据包,而远程设备没有确认接收时,会发送一个 TCP 重传数据包。一旦达到重传阈值,发送设备假设远程设备没有接收到数据,并重新传输该数据包。这个过程会重复几次,直到通信最终停止。

图 10-27:这些 TCP 重传数据包是潜在问题的迹象。
在这个场景中,重传是从客户端工作站发送到打印机的,因为打印机未能确认已传输的数据。如图 10-27 所示,如果你展开 TCP 头部的 SEQ/ACK 分析部分➊以及其下的附加信息,你可以查看为何这是一次重传的详细信息。根据 Wireshark 处理的细节,第 121 包是第 120 包的重传➌。此外,重传数据包的重传超时(RTO)大约是 5.5 秒➋。
在分析数据包之间的延迟时,你可以根据自己的情况调整时间显示格式。在本例中,由于我们希望查看重传发生在前一个数据包发送后多长时间,可以通过选择查看 ▶ 时间显示格式并选择自上一捕获数据包以来的秒数来更改此选项。然后,如图 10-28 所示,你可以清楚地看到,第 121 包的重传发生在原始数据包(第 120 包)发送后 5.5 秒➊。

图 10-28:查看数据包之间的时间对于故障排除非常有用。
下一个数据包是第 120 包的另一次重传。这个数据包的 RTO 是 11.10 秒,其中包括前一个数据包的 5.5 秒 RTO。从数据包列表窗格的时间列中,我们可以看到这次重传是在前一次重传后 5.6 秒发送的。这似乎是捕获文件中的最后一个数据包,并且巧合的是,打印机大约在此时停止打印。
在这个场景中,我们的优势是只涉及到两个设备,且都在我们自己的网络内,因此我们只需要确定是客户端工作站还是打印机出了问题。我们可以看到,数据流在一段时间内是正常的,然后在某个时刻,打印机就停止了响应工作站。工作站尽力将数据发送到目的地,正如重传所证明的那样,但结果没有任何响应。这个问题是可以重现的,并且无论哪台计算机发送打印任务都会发生,所以我们推测问题出在打印机上。
经过进一步分析,我们发现打印机的 RAM 出现故障。当大量打印任务发送到打印机时,它只能打印一定数量的页面,可能直到访问到内存的某些区域为止。此时,内存问题导致打印机无法接收任何新数据,并停止与发送打印任务的主机通信。
经验教训
尽管这次打印机问题并非由网络故障引起,但我们仍然能够使用 Wireshark 定位问题。与之前的场景不同,这次问题完全集中在 TCP 流量上。由于 TCP 关注的是可靠的数据传输,因此当两个设备停止通信时,它通常会留下有用的信息。
在这种情况下,当通信突然中断时,我们仅凭 TCP 的内建重传功能就能准确定位问题所在。在接下来的场景中,我们将经常依赖此类功能来排查更复杂的问题。
分支办公室无法连接
stranded_clientside.pcapng stranded_branchdns.pcapng
在这种情况下,我们有一家公司,拥有一个中央总部办公室和一个新部署的远程分支办公室。公司的 IT 基础设施大多集中在总部办公室,使用基于 Windows 服务器的域。该基础设施由一个域控制器、一个 DNS 服务器和一个应用服务器组成,后者用于托管公司员工每天使用的基于 Web 的软件。分支办公室通过路由器连接,建立广域网(WAN)连接。分支办公室内部有用户工作站和一个从属 DNS 服务器,应该从总部的上游 DNS 服务器接收其资源记录信息。图 10-29 展示了每个办公室的地图以及办公室之间的连接方式。

图 10-29:孤立分支办公室问题相关组件
部署团队正在向分支办公室部署新基础设施时发现,没有人能够从分支办公室网络访问内网 Web 应用服务器。该服务器位于总部,通过 WAN 链接进行访问。这个连接问题影响了分支办公室的所有用户。所有用户都能访问互联网以及分支办公室内的其他资源。
接入网络
因为问题出在总部和分支办公室之间的通信,我们可以从几个地方收集数据,以开始追踪问题。问题可能出在分支办公室内部的客户端,因此我们将从镜像其中一台计算机的端口开始,检查它在网络中看到的内容。一旦收集到这些信息,我们可以利用它指向其他收集点,以帮助解决问题。从其中一台客户端获取的初始捕获文件是stranded_clientside.pcapng。
分析
如图 10-30 所示,我们的第一个捕获文件开始于工作站地址 172.16.16.101 的用户尝试访问总部应用服务器 172.16.16.200 上托管的应用程序时。此捕获文件仅包含两个数据包。似乎第一个数据包发送了一个 DNS 请求到 172.16.16.251 ➊,请求appserver ➋的 A 记录 ➌。这是总部中央办公室中 172.16.16.200 服务器的 DNS 名称。
如图 10-31 所示,响应此数据包的是服务器故障 ➊,这表明某些因素正在阻止 DNS 查询成功解析。请注意,此数据包没有回答查询 ➋,因为它是一个错误(服务器故障)。

图 10-30:通信开始于 appserver A 记录的 DNS 查询。

图 10-31:查询响应表明上游存在问题。
我们现在知道,通信问题与某些 DNS 问题有关。由于分支办公室的 DNS 查询是由位于 172.16.16.251 的本地 DNS 服务器解析的,因此这是我们下一个要检查的地方。
为了捕获来自分支 DNS 服务器的适当流量,我们将保持嗅探器不变,只需更改端口镜像分配,使得现在镜像到嗅探器的流量来自 DNS 服务器,而不是工作站的流量。结果就是文件 stranded_branchdns.pcapng。
如图 10-32 所示,这次捕获从我们之前看到的查询和响应开始,并且有一个附加的数据包。这个附加的数据包看起来有点奇怪,因为它试图与总部的主 DNS 服务器(172.16.16.250) ➊ 在标准 DNS 服务器端口 53 ➌ 进行通信,但它不是我们习惯看到的 UDP ➋。

图 10-32:这个 SYN 数据包使用了 53 端口,但不是 UDP。
要弄清楚这个数据包的目的,回想一下我们在第九章中讨论的 DNS 内容。DNS 通常使用 UDP,但当查询的响应超过一定大小时,它会使用 TCP。在这种情况下,我们会看到一些初始的 UDP 流量,进而触发 TCP 流量。在 DNS 区域传输期间,当资源记录在 DNS 服务器之间传输时,TCP 也会被用于 DNS,这很可能就是这里的情况。
分支办公室的 DNS 服务器是总部 DNS 服务器的从服务器,这意味着它依赖于总部 DNS 服务器来接收资源记录。分支办公室用户尝试访问的应用服务器位于总部内部,这意味着总部 DNS 服务器对该服务器具有权威性。为了让分支办公室的服务器解析应用服务器的 DNS 请求,该服务器的 DNS 资源记录必须从总部 DNS 服务器传输到分支办公室 DNS 服务器。这很可能就是这个捕获文件中 SYN 数据包的来源。
对这个 SYN 数据包没有响应告诉我们,DNS 问题是由于分支和总部 DNS 服务器之间的区域传输失败导致的。现在我们可以进一步探究区域传输失败的原因。可能的原因可以缩小到办公室之间的路由器或总部 DNS 服务器本身。为了确定是哪一方出现问题,我们可以嗅探总部 DNS 服务器的流量,看看 SYN 数据包是否到达了服务器。
我没有包括中央办公室 DNS 服务器流量的捕获文件,因为没有此类流量。SYN 数据包从未到达服务器。在派遣技术人员检查连接两地办公室路由器的配置时,发现中央办公室路由器的入站 53 端口流量配置仅允许 UDP 流量,阻止了入站的 TCP 流量。这个简单的配置错误导致了服务器之间的区域传输失败,从而阻止了分支办公室的客户端解析中央办公室设备的查询。
经验教训
通过观看犯罪剧,你可以学到很多关于调查网络通信问题的技巧。当犯罪发生时,侦探们通常会从最受影响的人开始采访。由此得到的线索会被追踪,直到最终找出罪犯。
在这个场景中,我们首先检查了目标(工作站),并通过发现 DNS 通信问题获得了线索。我们的线索引导我们来到了分支 DNS 服务器,然后是中央 DNS 服务器,最后是路由器,最终找到了问题的根源。
在进行分析时,试着将数据包视为线索。这些线索并不总是能直接告诉你谁是罪犯,但它们通常最终会将你引向罪犯。
软件数据损坏
tickedoffdeveloper.pcapng
IT 领域最常见的争论之一发生在开发人员和网络管理员之间。开发人员总是将程序错误归咎于网络工程不良和设备故障。而网络管理员则往往将网络错误和通信延迟归咎于坏代码。
在这个场景中,一名程序员开发了一个用于追踪多家商店销售情况并将数据回传至中央数据库的应用程序。为了节省在正常营业时间的带宽,应用程序不会实时更新。数据在一天中不断积累,然后在晚上作为逗号分隔值(CSV)文件传输,并插入到中央数据库中。
这个新开发的应用程序没有正常工作。来自商店的文件虽然被服务器接收到,但插入数据库的数据并不正确。部分内容缺失,数据放错了位置,有些数据甚至完全丢失。令网络管理员十分沮丧的是,程序员将问题归咎于网络。他们坚信文件在从商店传输到中央数据存储库的过程中发生了损坏。我们的目标是确定他们的判断是否正确。
深入探测网络
为了收集所需的数据,我们可以在其中一家商店或中央办公室捕获数据包。因为这个问题影响到所有商店,如果问题是网络相关的,那么它应该在中央办公室发生——这是所有商店的共同点(除了软件本身)。
网络交换机支持端口镜像,因此我们将镜像服务器所在端口,并嗅探其流量。流量捕获将被限制为商店将其 CSV 文件上传到集合服务器的单一实例。该结果即为捕获文件* tickenoffdeveloper.pcapng*。
分析
我们对程序员开发的应用了解不多,除了网络上的基本信息流动。捕获文件似乎是从一些 FTP 流量开始的,因此我们将进行调查,看它是否真的是传输此文件的机制。
首先查看包列表(图 10-33),我们可以看到 172.16.16.128 ➊发起了与 172.16.16.121 ➋的 TCP 握手通信。由于 172.16.16.128 发起了通信,我们可以假设它是客户端,而 172.16.16.121 是编译和处理数据的服务器。完成握手后,我们开始看到来自客户端的 FTP 请求和来自服务器的响应 ➌。

图 10-33:初始通信有助于识别客户端和服务器。
我们知道这里应该发生一些数据传输,因此我们可以利用 FTP 的知识来定位数据传输开始的包。FTP 连接和数据传输是由客户端发起的,所以从 172.16.16.128 我们应该能看到 FTP 的STOR命令,这是用来上传数据到 FTP 服务器的。找到这个命令的最简单方法是构建一个过滤器。
由于该捕获文件中充满了 FTP 请求命令,我们不需要在表达式构建器中筛选数百个协议和选项,而是可以直接从包列表窗格中构建所需的过滤器。为此,我们首先需要选择一个包含 FTP 请求命令的包。我们选择第 5 个包,因为它靠近列表顶部。然后展开包详细信息窗格中的 FTP 部分,并展开 USER 部分。右键点击请求命令:USER字段并选择准备过滤器。最后,选择选定。
这将为所有包含FTP USER请求命令的包准备一个过滤器,并将其放入过滤器对话框中。接下来,如图 10-34 所示,编辑过滤器,将USER替换为STOR ➊。

图 10-34:此过滤器有助于识别数据传输的开始位置。
我们可以通过提供客户端的 IP 地址并将其指定为连接的来源,进一步缩小过滤器范围,通过在过滤器中添加&& ip.src == 172.16.16.128,但由于该捕获文件已经限制为单一客户端,因此在这里并不需要。
现在按下 ENTER 应用这个过滤器,你会看到在捕获文件中只有一个STOR命令实例,出现在第 64 个包 ➋。
现在我们知道数据传输的起始位置,点击该包进行选择,然后通过点击包列表窗格上方的X按钮清除筛选器。此时,您的屏幕应该显示所有数据包,并且包 64 已被选中。
检查从包 64 开始的捕获文件,我们看到该包指定了文件store4829-03222010.csv的传输➊,如图 10-35 所示。

图 10-35:CSV 文件正在通过 FTP 传输。
紧随STOR命令的包使用了不同的端口,但被识别为 FTP-DATA 传输的一部分。我们已经验证了数据正在传输,但我们尚未确定程序员是否正确。为了做到这一点,我们需要展示文件内容在穿越网络后是否完整,因此我们将继续从捕获的包中提取传输的文件。
当文件以未加密的格式通过网络传输时,它会被分解成多个片段,并在目标处重新组装。在此场景中,我们捕获了到达目标的包,但在它们被重新组装之前。数据是完整的;我们只需要通过提取数据流来重新组装它。为了执行重新组装,选择 FTP-DATA 流中的任何包(例如包 66),然后点击跟踪 TCP 流。结果将如图 10-36 所示。看起来像一个包含销售订单数据的正常 CSV 格式文本文件。
数据出现是因为它通过 FTP 以明文形式传输,但仅凭流数据我们无法确定文件是否完整。为了重新组装数据并以原始格式提取它,请点击另存为按钮,并指定文件名,如包 64 中所示。然后点击保存。
此保存操作的结果应为一个 CSV 文件,它是从商店系统原始传输文件的精确字节级副本。可以通过比较原始文件的 MD5 哈希值与提取文件的 MD5 哈希值来验证该文件。MD5 哈希值应该是相同的,如图 10-37 所示。

图 10-36:TCP 流显示的是似乎正在传输的数据。

图 10-37:原始文件和提取文件的 MD5 哈希值是相等的。
一旦文件被比较,我们可以断言,网络并不是导致应用程序中数据库损坏的原因。从商店到集线器服务器传输的文件在到达服务器时是完整的,因此任何损坏都必须发生在文件由服务器端应用程序处理时。
经验教训
数据包级分析的一个优点是,你不需要处理应用程序的杂乱。编写不良的应用程序数量远远超过了优秀的应用程序,但在数据包级别,这些都不重要。在这个案例中,程序员担心他们的应用程序所依赖的所有神秘组件,但归根结底,他们复杂的数据传输——那些需要数百行代码的内容——仍然不过是 FTP、TCP 和 IP。利用我们对这些基本协议的了解,我们能够确保通信过程正常流畅,甚至提取文件以证明网络的可靠性。必须记住,不论问题多么复杂,最终归结起来还是数据包的问题。
最终思考
在本章中,我们讨论了几个通过数据包分析帮助我们更好地理解通信问题的场景。通过对常见协议的基本分析,我们能够及时跟踪并解决网络问题。虽然在你的网络中可能不会遇到完全相同的场景,但这里介绍的分析技术应该对你分析自己独特的问题有所帮助。
第十一章:对抗慢速网络

作为网络管理员,您大部分时间都会花在修复运行速度慢的计算机和服务上。但仅仅因为有人说网络运行缓慢,并不意味着网络就是问题的根源。
在开始解决慢速网络问题之前,您首先需要确定网络是否确实运行缓慢。您将在本章中学习如何做到这一点。
我们将首先讨论 TCP 的错误恢复和流控制功能。接着我们将探讨如何检测网络上的慢速来源。最后,我们将研究如何基准测试网络以及运行在其上的设备和服务。完成本章后,您将更好地准备识别、诊断和排除慢速网络问题。
注意
有多种技术可以用于排查慢速网络问题。我选择主要聚焦于 TCP,因为大多数时候,它是您可以使用的唯一工具。TCP 允许您进行被动回顾性分析,而无需生成额外的流量(与 ICMP 不同)。
TCP 错误恢复特性
TCP 的错误恢复特性是我们定位、诊断并最终修复网络高延迟的最佳工具。在计算机网络中,延迟是指数据包传输和接收之间的延迟时间。
延迟可以以单程(从单一来源到目的地)或往返(从来源到目的地再返回到原始来源)来衡量。当设备之间的通信速度快,数据包从一个点传输到另一个点的时间较短时,通信被认为是低延迟的。相反,当数据包在源和目的地之间传输所需时间较长时,通信被认为是高延迟的。高延迟是所有网络管理员的头号敌人,尤其是那些珍惜自己理智(和工作)的管理员。
在第八章中,我们讨论了 TCP 如何使用序列号和确认号来确保数据包的可靠传输。在本章中,我们将再次查看序列号和确认号,了解当高延迟导致这些数字按顺序接收(或根本没有接收)时,TCP 是如何响应的。
TCP 重传
tcp_retransmissions.pcapng
主机重新传输数据包的能力是 TCP 最基本的错误恢复特性之一。它旨在应对数据包丢失问题。
数据包丢失的原因有很多种,包括应用程序故障、路由器负载过重或临时服务中断。在数据包层面,事情发生得非常快,而且数据包丢失通常是暂时的,因此 TCP 能够检测并恢复数据包丢失至关重要。
确定是否需要重传数据包的主要机制是 重传计时器。该计时器负责维护一个名为 重传超时(RTO) 的值。每当使用 TCP 发送数据包时,重传计时器会启动。当该数据包的 ACK 被接收到时,计时器停止。数据包传输和接收 ACK 数据包之间的时间称为 往返时间(RTT)。这些时间的平均值会被用来确定最终的 RTO 值。
在确定 RTO 值之前,发送操作系统依赖其默认配置的 RTT 设置,该设置用于主机间的初始通信。然后,这个值会根据接收数据包的 RTT 进行调整,以确定最终的 RTO 值。
一旦 RTO 值确定,重传计时器就会在每个传输的数据包上使用,以确定是否发生了数据包丢失。图 11-1 展示了 TCP 重传过程。

图 11-1:TCP 重传过程的概念视图
当一个数据包发送出去,但接收方没有返回 TCP ACK 数据包时,发送主机会假设原始数据包丢失,并重新发送该数据包。当重传被发送时,RTO 值会加倍;如果在达到该值之前没有收到 ACK 数据包,就会发生另一轮重传。如果这次重传仍然没有收到 ACK 响应,RTO 值会再次加倍。这个过程会继续进行,每次重传时 RTO 值都会加倍,直到收到 ACK 数据包或发送方达到它配置的最大重传次数为止。关于这个过程的更多细节可以参考 RFC6298。
最大的重传尝试次数取决于发送操作系统中配置的值。默认情况下,Windows 主机会进行最多五次重传尝试。大多数 Linux 主机默认最大重传尝试次数为 15 次。这个选项在两个操作系统中都可以进行配置。
作为 TCP 重传的一个示例,打开文件 tcp_retransmissions.pcapng,该文件包含六个数据包。第一个数据包如图 11-2 所示。

图 11-2:包含数据的简单 TCP 数据包
这个数据包是一个 TCP PSH/ACK 数据包 ➋,包含 648 字节的数据 ➌,从 10.3.30.1 发送到 10.3.71.7 ➊。这是一个典型的数据包。
在正常情况下,你可以期望在发送第一个数据包后不久看到一个 TCP ACK 数据包作为响应。然而,在这种情况下,下一个数据包是重传。你可以通过查看数据包列表窗格中的数据包来判断这一点。信息列会清楚地显示[TCP Retransmission],并且数据包会以红色文本显示在黑色背景上。图 11-3 显示了数据包列表窗格中列出的重传示例。

图 11-3:数据包列表窗格中的重传
你还可以通过在数据包详细信息窗格中检查数据包,来判断它是否为重传,如图 11-4 所示。
在数据包详细信息窗格中,可以看到重传的数据包在 SEQ/ACK 分析标题下有一些附加信息 ➊。此有用信息由 Wireshark 提供,而不包含在数据包本身中。SEQ/ACK 分析告诉我们,这确实是一个重传 ➋,RTO 值为 0.206 秒 ➌,并且 RTO 是基于数据包 1 的时间差 ➍。

图 11-4:单个重传数据包
请注意,此数据包与原始数据包相同(除了 IP 标识符和校验和字段)。为验证这一点,比较此重传数据包与原始数据包的“数据包字节”窗格。
检查其余的数据包应得出类似的结果,数据包之间的唯一差异存在于 IP 标识符、校验和字段和 RTO 值中。要查看每个数据包之间的时间间隔,请查看数据包列表窗格中的时间列,如图 11-5 所示。在这里,你可以看到随着每次重传,RTO 值的指数增长。
TCP 重传功能被发送设备用于检测和恢复丢包。接下来,我们将探讨TCP 重复确认功能,这是数据接收方用来检测和恢复丢包的一项特性。

图 11-5:时间列显示 RTO 值的增加。
TCP 重复确认与快速重传
tcp_dupack.pcapng
重复 ACK 是接收方在接收到乱序的数据包时发送的 TCP 数据包。TCP 使用其头部中的序列号和确认号字段,可靠地确保数据按照发送的顺序接收并重新组装。
注意
TCP 数据包的正确术语实际上是 TCP 段,但大多数人称其为数据包。
当建立一个新的 TCP 连接时,握手过程中交换的最重要的信息之一是初始序列号(ISN)。一旦为连接的每一端设置了 ISN,每个随后传输的包都会根据其数据负载的大小递增序列号。
考虑一个 ISN 为 5000 的主机,它向接收方发送一个 500 字节的数据包。一旦这个数据包被接收,接收方主机将以确认号 5500 响应一个 TCP 确认包,基于以下公式:
序列号输入 + 接收的数据字节 = 确认号输出
根据这个计算,返回给发送主机的确认号是接收方预计接收的下一个序列号。这个例子可以在图 11-6 中看到。

图 11-6:TCP 序列号和确认号
数据接收方通过序列号检测数据包丢失的能力。随着接收方跟踪接收到的序列号,它可以判断何时收到的序列号是乱序的。
当接收方收到一个意外的序列号时,它会认为数据包在传输过程中丢失了。为了正确地重新组装数据,接收方必须拥有丢失的数据包,因此它会重新发送包含丢失数据包预期序列号的确认包,以便从发送主机请求重新传输该数据包。
当发送主机收到接收方的三个重复确认包时,它会认为数据包确实在传输过程中丢失,并立即发送一个快速重传。一旦触发快速重传,所有其他正在传输的数据包都会被排队,直到快速重传的数据包发送完毕。这个过程在图 11-7 中有所展示。

图 11-7:接收方的重复确认包导致快速重传。
在文件tcp_dupack.pcapng中,你可以找到重复确认包和快速重传的示例。此捕获中的第一个数据包显示在图 11-8 中。

图 11-8:显示下一个预期序列号的确认包
这个数据包,一个从数据接收方(172.31.136.85)到发送方(195.81.202.68)发送的 TCP 确认包 ➊,包含对前一个数据包中发送的数据的确认,这些数据不包含在此捕获文件中。
注意
默认情况下,Wireshark 使用相对序列号使得这些数字的分析更加容易,但接下来的几个部分中的示例和截图并未使用此功能。要关闭此功能,请选择 编辑 ▶ 首选项。在首选项窗口中,选择* 协议,然后选择* TCP 部分。然后取消选中 相对序列号 旁边的复选框。
这个数据包中的确认号是 1310973186 ➋。它应该与接收到的下一个数据包中的序列号相匹配,如图 11-9 所示。

图 11-9:这个数据包的序列号不是预期的序列号。
不幸的是,对于我们和接收方来说,下一个数据包的序列号是 1310984130 ➊,这不是我们预期的。这一错乱的数据包表明预期的数据包在传输过程中丢失了。接收主机注意到该数据包顺序错乱,并在本次捕获的第三个数据包中发送了一个重复 ACK,如图 11-10 所示。
你可以通过以下任意一种方式来确定这是一个重复 ACK 数据包:
• 数据包详情窗格中的“信息”列。该数据包应该以红色文本显示在黑色背景上。
• SEQ/ACK 分析标题下的数据包详情窗格(图 11-10)。如果展开该标题,你会发现该数据包被列为数据包 1 ➊ 的重复 ACK。

图 11-10:第一个重复 ACK 数据包
接下来的几个数据包继续这个过程,如图 11-11 所示。

图 11-11:由于数据包顺序错乱,产生了额外的重复 ACK。
捕获文件中的第四个数据包是另一个从发送主机发送的带有错误序列号 ➊的数据块。因此,接收主机发送了第二个重复 ACK ➋。接收主机又接收到一个带有错误序列号的数据包 ➌,这导致它发送了第三个也是最后一个重复 ACK ➍。
一旦发送方主机接收到收件方的第三个重复 ACK,它必须停止所有数据包传输并重新发送丢失的数据包。图 11-12 展示了丢失数据包的快速重传。
通过数据包列表窗格中的信息列,你可以再次找到重传的数据包。与之前的示例一样,该数据包明确标注为红色文本显示在黑色背景上。该数据包的 SEQ/ACK 分析部分(图 11-12)告诉我们这是一个疑似的快速重传 ➊。(再次说明,标记此数据包为快速重传的信息并非数据包本身设置的值,而是 Wireshark 的一项特性。)捕获中的最后一个数据包是一个 ACK 数据包,确认已收到快速重传的数据包。

图 11-12:三个重复 ACK 导致了该丢失数据包的快速重传。
注意
在 TCP 通信中,当出现丢包时,可能影响数据流动的一个特点是选择性确认(Selective Acknowledgment)功能。在我们刚刚检查的包捕获中,选择性确认在初始的三次握手过程中被协商为启用的功能。因此,每当发生丢包并收到重复确认时,只有丢失的数据包需要重新传输,即使在丢失的数据包之后,其他数据包已经成功接收。如果没有启用选择性确认,丢失数据包之后的每个数据包都需要重新传输。选择性确认使得数据丢失恢复更加高效。由于大多数现代 TCP/IP 协议栈实现都支持选择性确认,因此你会发现这一功能通常是已实现的。
TCP 流量控制
重新传输和重复确认是 TCP 的反应式功能,旨在从丢包中恢复。如果 TCP 没有包含某种形式的主动方法来防止丢包,它将是一个非常糟糕的协议。
TCP 实现了一个滑动窗口机制,用于检测何时可能发生丢包,并调整数据传输速率以防止丢包。滑动窗口机制利用数据接收方的接收窗口来控制数据流。
接收窗口是由数据接收方指定并存储在 TCP 头部(以字节为单位)的一个值,告知发送设备接收方愿意在其TCP 缓冲区空间中存储多少数据。这个缓冲区空间是数据暂时存储的地方,直到它可以被传递到栈上等待处理的应用层协议。因此,发送方一次只能发送接收方在窗口大小字段中指定的数量的数据。为了让发送方发送更多数据,接收方必须发送确认,表示先前的数据已经接收。同时,它还必须通过处理占用该位置的数据来清理 TCP 缓冲区空间。图 11-13 说明了接收窗口的工作原理。

图 11-13:接收窗口防止数据接收方被淹没。
在图 11-13 中,客户端正在向服务器发送数据,服务器已传达接收窗口大小为 5,000 字节。客户端发送了 2,500 字节,减少了服务器的缓冲区空间至 2,500 字节,然后又发送了 2,000 字节,进一步将缓冲区减少至 500 字节。服务器对此数据发送了确认,并在处理完缓冲区中的数据后,缓冲区变为空。这个过程会重复,客户端发送 3,000 字节和另外 1,000 字节,减少服务器缓冲区至 1,000 字节。客户端再次确认这些数据并处理缓冲区中的内容。
调整窗口大小
调整窗口大小的过程相当直接,但并不总是完美的。每当 TCP 栈接收到数据时,都会生成并发送一个确认响应,但并不是所有放入接收方缓冲区的数据都会立即被处理。
当一台繁忙的服务器正在处理来自多个客户端的数据包时,它很可能在清空其缓冲区时变得缓慢,从而无法为新数据腾出空间。如果没有流量控制机制,缓冲区满了可能会导致数据包丢失和数据损坏。幸运的是,当服务器变得过于繁忙,无法按照其接收窗口所广告的速率处理数据时,它可以调整窗口大小。它通过减少在返回给发送数据的主机的 ACK 数据包中的 TCP 头部窗口大小值来做到这一点。图 11-14 展示了这一过程的示例。

图 11-14:当服务器变得繁忙时,窗口大小可以调整。
在图 11-14 中,服务器开始时的广告窗口大小为 5000 字节。客户端发送了 2000 字节,然后又发送了 2000 字节,剩下的缓冲区空间只有 1000 字节。服务器意识到其缓冲区正在快速填满,并知道如果数据传输以此速度继续进行,数据包很快就会丢失。为了避免这种意外,服务器向客户端发送了一个更新后的窗口大小为 1000 字节的确认数据包。客户端通过发送较少的数据进行响应,现在服务器处理缓冲区内容的速率使得数据能够以稳定的方式流入。
窗口大小调整的过程是双向的。当服务器可以以更快的速率处理数据时,它可以发送一个带有更大窗口大小的 ACK 数据包。
通过零窗口通知停止数据流
由于内存不足、处理能力不足或其他问题,服务器可能不再处理来自客户端的数据。这种停止可能导致数据包丢失并中断通信过程,但接收窗口可以最小化负面影响。
当这种情况发生时,服务器可以发送一个包含零窗口大小的数据包。当客户端接收到此数据包时,它会停止所有数据传输,但有时会保持与服务器的连接,通过传输保持连接数据包。客户端可以定期发送保持连接数据包,以检查服务器接收窗口的状态。一旦服务器可以再次开始处理数据,它将以非零窗口大小响应,通信将恢复。图 11-15 展示了零窗口通知的示例。

图 11-15:当窗口大小设置为 0 字节时,数据传输停止。
在图 11-15 中,服务器开始以 5,000 字节的窗口大小接收数据。在从客户端接收到总计 4,000 字节的数据后,服务器开始经历非常高的处理器负载,无法再处理来自客户端的任何数据。然后,服务器发送一个数据包,将窗口大小值字段设置为 0。客户端停止发送数据,并发送一个保持连接的数据包。在接收到保持连接的数据包后,服务器回应一个数据包,通知客户端它现在可以接收数据,并且其窗口大小为 1,000 字节。客户端恢复发送数据,但速度比之前慢。
实际中的 TCP 滑动窗口
tcp_zerowindow recovery.pcapng tcp_zerowindow dead.pcapng
在讲解完 TCP 滑动窗口的理论后,我们将开始检查捕获文件tcp_zerowindowrecovery.pcapng中的实际情况。
在这个文件中,我们首先看到几个从 192.168.0.20 发送到 192.168.0.30 的 TCP ACK 数据包。我们最关心的值是窗口大小值字段,可以在数据包列表窗格的“信息”列和数据包详细信息窗格中的 TCP 头部看到。你可以立即看到,这个字段的值在前三个数据包中逐渐减小,如图 11-16 所示。

图 11-16:这些数据包的窗口大小正在减小。
窗口大小值从第一个数据包中的 8,760 字节下降到第二个数据包的 5,840 字节,再到第三个数据包的 2,920 字节 ➋。窗口大小值的下降是主机延迟增加的经典指示器。请注意,在“时间”列中,这一过程发生得非常迅速 ➊。当窗口大小如此快速下降时,窗口大小通常会降到零,这正是第四个数据包中的情况,如图 11-17 所示。

图 11-17:这个零窗口数据包表示主机无法再接收任何数据。
第四个数据包也从 192.168.0.20 发送到 192.168.0.30,但它的目的是告诉 192.168.0.30,它已经无法再接收任何数据。TCP 头部中看到的 0 值 ➊。Wireshark 还告诉我们,这是一个零窗口数据包,显示在数据包列表窗格的“信息”列和 TCP 头部的 SEQ/ACK 分析部分 ➋。
一旦这个零窗口数据包被发送,位于 192.168.0.30 的设备将不会再发送任何数据,直到它收到来自 192.168.0.20 的窗口更新,通知它窗口大小已经增大。幸运的是,这个捕获文件中的零窗口问题只是暂时的。因此,在下一个数据包中发送了一个窗口更新,如图 11-18 所示。
在这种情况下,窗口大小增加到了一个非常健康的 64,240 字节 ➊。Wireshark 再次告知我们,这是一个在 SEQ/ACK 分析标题下的窗口更新。
一旦更新包被接收,位于 192.168.0.30 的主机可以重新开始发送数据,就像在数据包 6 和 7 中所做的那样。整个数据传输暂停的过程发生得非常迅速。如果这一过程稍微长一点,它可能会导致网络出现潜在的卡顿,导致数据传输变慢或失败。

图 11-18:TCP 窗口更新数据包让另一台主机知道它可以重新开始传输。
再次查看滑动窗口,检查 tcp_zerowindowdead.pcapng。此捕获中的第一个数据包是从 195.81.202.68 发送到 172.31.136.85 的正常 HTTP 流量。该数据包后面紧跟着一个从 172.31.136.85 发送回来的零窗口数据包,如图 11-19 所示。

图 11-19:零窗口数据包暂停数据传输。
这看起来与图 11-17 中显示的零窗口数据包非常相似,但结果却大不相同。我们没有看到来自 172.31.136.85 主机的窗口更新以及通信的恢复,而是看到一个保持连接的数据包,如图 11-20 所示。

图 11-20:该保持连接数据包确保零窗口主机仍然存活。
该数据包在 Wireshark 中被标记为保持连接数据包,位于数据包详细信息面板的 TCP 头部 SEQ/ACK 分析部分 ➊。时间列显示该数据包是在收到上一个数据包后 3.4 秒发送的。这个过程还会继续几次,一台主机发送零窗口数据包,另一台主机发送保持连接数据包,如图 11-21 所示。

图 11-21:主机和客户端继续分别发送零窗口和保持连接数据包。
这些保持连接的数据包间隔为 3.4 秒、6.8 秒和 13.5 秒 ➊。这个过程可以持续很长时间,具体取决于通信设备的操作系统。通过累加时间列中的值,可以看到连接被暂停了将近 25 秒。想象一下,在进行域控制器身份验证或从互联网下载文件时,经历 25 秒的延迟——这是无法接受的!
从 TCP 错误控制和流量控制数据包中学习
让我们将重传、重复 ACK 和滑动窗口机制放入一些背景中。在排查延迟问题时,记住以下几点。
重传数据包
重传发生是因为客户端检测到服务器没有接收到它发送的数据。因此,根据你分析的通信方,可能永远看不到重传。如果你从服务器端捕获数据,并且服务器确实没有接收到客户端发送并重传的数据包,你可能一无所知,因为你看不到重传的数据包。如果你怀疑自己在服务器端遭遇了数据包丢失,考虑尝试从客户端捕获流量(如果可能的话),这样你就可以看到是否存在重传数据包。
重复 ACK 数据包
我倾向于将重复 ACK 视为重传的伪相反,因为它是在服务器检测到与之通信的客户端丢失数据包时发送的。在大多数情况下,你可以在捕获两端的流量时看到重复 ACK。记住,重复 ACK 是在数据包按顺序接收时触发的。例如,如果服务器只接收到三包数据中的第一包和第三包,它会发送一个重复 ACK,以促使客户端快速重传第二个数据包。由于已经接收到第一包和第三包,因此导致第二包丢失的条件很可能是暂时性的,因此重复 ACK 很可能会成功发送和接收。当然,这种情况并不总是如此,所以当你怀疑服务器端丢包并且没有看到任何重复 ACK 时,考虑从客户端侧捕获数据包。
零窗口和保持活动数据包
滑动窗口直接与服务器无法接收和处理数据有关。窗口大小的任何减少或零窗口状态都是服务器存在问题的直接结果,因此,如果你在网络上传输中看到这些情况,你应该将调查重点放在那里。你通常会在网络通信的两端看到窗口更新数据包。
定位高延迟的来源
在某些情况下,数据包丢失可能不是延迟的原因。你可能会发现,即使两个主机之间的通信很慢,这种慢速并没有显示出 TCP 重传或重复 ACK 的常见症状。因此,你需要使用其他技术来定位高延迟的来源。
查找高延迟来源的一个有效方法是检查初始连接握手以及随后的前几个数据包。例如,考虑一个简单的客户端和 Web 服务器之间的连接,客户端尝试浏览托管在 Web 服务器上的网站。我们关心的是这次通信序列中的前六个数据包,包括 TCP 握手、初始 HTTP GET请求、该GET请求的确认以及服务器发送到客户端的第一个数据包。
注意
要跟随本节内容,请确保在 Wireshark 中设置了正确的时间显示格式,选择视图* ▶ 时间显示格式 ▶ 自上次显示的数据包以来的秒数。*
正常通信
latency1.pcapng
稍后我们将在本章中详细讨论网络基线。现在,只需要知道你需要一个正常通信的基线,以便与高延迟的情况进行比较。对于这些示例,我们将使用文件latency1.pcapng。我们已经涵盖了 TCP 握手和 HTTP 通信的细节,因此不再重复这些主题。事实上,我们根本不需要查看数据包详情面板。我们真正关心的是“时间”这一列,如图 11-22 所示。

图 11-22:这种流量发生得非常快,可以视为正常。
这段通信序列非常快速,整个过程耗时不到 0.1 秒。
接下来我们将检查的几个捕获文件将包含相同的流量模式,只是数据包的时间有所不同。
慢速通信:线缆延迟
latency2.pcapng
现在让我们来看看捕获文件latency2.pcapng。请注意,所有数据包内容相同,唯一的不同是其中两个数据包的时间值,正如图 11-23 所示。

图 11-23:数据包 2 和 5 显示了较高的延迟。
当我们开始逐一分析这六个数据包时,立刻就遇到了第一个延迟的迹象。初始的 SYN 数据包由客户端(172.16.16.128)发送,用于启动 TCP 握手,而在接收到来自服务器(74.125.95.104)返回的 SYN/ACK 之前,出现了 0.87 秒的延迟。这是我们首次发现存在线缆延迟的迹象,延迟是由于客户端和服务器之间的某个设备造成的。
我们可以判断这是线缆延迟,因为传输的数据包类型的特性。当服务器接收到 SYN 数据包时,回复所需的处理非常少,因为工作负载不涉及超出传输层的任何处理。即使服务器在承受非常重的流量负载时,通常也会迅速回应 SYN 数据包并发送 SYN/ACK。这排除了服务器作为高延迟的潜在原因。
客户端也被排除了,因为此时它仅仅是在接收 SYN/ACK 数据包,并未进行任何进一步处理。排除客户端和服务器后,我们可以将慢速通信的潜在来源指向此捕获的前两个数据包。
继续观察,我们看到完成三次握手的 ACK 数据包传输非常快,客户端发送的 HTTP GET请求也是如此。所有生成这两个数据包的处理都发生在客户端本地,在收到 SYN/ACK 之后,因此只要客户端没有面临重负载,这两个数据包应该会很快传输。
在数据包 5 处,我们看到另一个数据包具有非常高的时间值。看起来,在我们发送初始的 HTTP GET请求后,服务器返回的 ACK 数据包花费了 1.15 秒才被接收。在收到 HTTP GET请求后,服务器发送了一个 TCP ACK,随后才开始发送数据,这又一次表明服务器几乎没有处理负担。这是网络延迟的另一个迹象。
每当你遇到网络延迟时,你几乎总是会在初始握手中的 SYN/ACK 以及通信过程中其他 ACK 数据包中看到它。尽管这些信息不能告诉你网络中高延迟的确切来源,但它能告诉你,既不是客户端也不是服务器是延迟的源头,因此你知道延迟是由中间的某个设备引起的。此时,你可以开始检查各种防火墙、路由器和代理,以定位罪魁祸首。
慢速通信:客户端延迟
latency3.pcapng
接下来的延迟场景我们将在latency3.pcapng中查看,如图 11-24 所示。

图 11-24:此抓包中的慢速数据包是初始的 HTTP GET。
这个抓包正常开始,TCP 握手非常快速地完成,没有任何延迟的迹象。直到数据包 4,它是握手完成后的 HTTP GET请求。这个数据包显示出从前一个接收到的数据包的 1.34 秒延迟。
要确定这个延迟的来源,我们需要检查数据包 3 和数据包 4 之间发生了什么。数据包 3 是客户端发送到服务器的 TCP 握手中的最后一个 ACK,而数据包 4 是客户端发送到服务器的GET请求。这里的共同点是,这两个数据包都是客户端发送的,并且与服务器无关。GET请求应该在 ACK 发送后迅速发生,因为所有这些动作都集中在客户端。
对最终用户来说,不幸的是,从 ACK 到GET的过渡并不会很快发生。GET数据包的创建和传输需要处理到应用层,而这一处理的延迟表明客户端未能及时执行该操作。因此,客户端最终对通信中的高延迟负责。
慢速通信:服务器延迟
latency4.pcapng
我们将要检查的最后一个延迟场景使用文件latency4.pcapng,如图 11-25 所示。这是一个服务器延迟的示例。

图 11-25:直到这次捕获的最后一个数据包才表现出高延迟。
在这次捕获中,这两台主机之间的 TCP 握手过程完成得非常顺利且快速,因此一切开始得很好。接下来的几个数据包也带来了好消息,因为初始的GET请求和响应 ACK 数据包也很快被传送。直到该文件的最后一个数据包,我们才看到高延迟的迹象。
第六个数据包是服务器响应客户端发送的GET请求的第一个 HTTP 数据包,在服务器发送完GET请求的 TCP ACK 后,延迟到达时间为 0.98 秒。数据包 5 和 6 之间的过渡非常类似于我们在之前场景中看到的握手 ACK 和GET请求之间的过渡。然而,在这种情况下,服务器是我们关注的重点。
数据包 5 是服务器在响应客户端的GET请求时发送的 ACK 数据包。一旦该数据包发送完,服务器应几乎立即开始发送数据。数据包中数据的访问、打包和传输是由 HTTP 协议完成的,鉴于这是一个应用层协议,服务器需要进行一些处理。此数据包的接收延迟表明服务器未能在合理的时间内处理该数据,最终将其指向为此捕获文件中的延迟源。
延迟定位框架
通过六个数据包,我们已经能够在多个场景中定位客户端与服务器之间的高网络延迟源。图 11-26 应当能帮助你排查自己的延迟问题。这些原则可以应用于几乎所有基于 TCP 的通信。

图 11-26:此图可用于排查你的延迟问题。
注意
请注意,我们没有详细讨论 UDP 延迟。由于 UDP 设计上是快速但不可靠的,它没有任何内置的特性来检测和恢复延迟。相反,它依赖于与之配对的应用层协议(和 ICMP)来处理数据传输的可靠性。
网络基准
当其他方法都失败时,你的网络基准可以是排查网络延迟问题时最重要的数据之一。就我们的目的而言,网络基准由来自网络各个点的流量样本组成,包含了我们认为的“大部分正常”网络流量。建立网络基准的目标是,它可以作为比较的基础,当网络或其上的设备出现异常时,进行分析。
例如,考虑一个场景,网络上的几个客户端在登录本地 Web 应用服务器时抱怨慢。如果您捕获了这段流量并将其与网络基线进行比较,您可能会发现 Web 服务器的响应是正常的,但由于 Web 应用中嵌入的外部内容,外部 DNS 请求的响应速度只有正常的两倍。
您可能已经在没有网络基线的帮助下注意到慢速外部 DNS 服务器,但当您处理的是微小的变化时,情况可能并非如此。十个 DNS 查询处理时间比正常情况多 0.1 秒,和一个 DNS 查询多 1 秒的情况一样糟糕,但前者在没有网络基线的情况下更难以发现。
因为没有两个网络是完全相同的,所以网络基线的组成部分可能会有很大差异。以下部分提供了网络基线组成部分的示例。您可能会发现这些项目中的所有内容都适用于您的网络基础设施,或者只有很少一部分适用。无论如何,您应该能够将基线的每个组成部分归类到三个基本基线类别之一:站点、主机和应用程序。
站点基线
网站基线的目的是获取网络中每个物理站点的流量概况。理想情况下,这应包括广域网的每个段。
这个基线的组成部分可能包括以下内容:
正在使用的协议
要查看来自所有设备的流量,请在捕获来自网络边缘(路由器/防火墙)上所有设备的流量时,使用协议层次统计窗口(统计 ▶ 协议层次)。之后,您可以将其与层次输出进行比较,找出是否缺少常见协议,或是否有新协议在网络中出现。您还可以使用此输出根据协议查找异常的某些类型的流量。
广播流量
这包括网络段上的所有广播流量。在站点内的任何位置嗅探都应该让您捕获到所有的广播流量,从而让您知道谁或什么通常在网络上发送大量的广播。然后,您可以快速判断是否存在过多(或不足)的广播。
认证序列
这些包括从随机客户端到所有服务的身份验证过程流量,如活动目录、Web 应用程序和特定于组织的软件。身份验证是服务常常变慢的一个领域。基线可以帮助您判断身份验证是否是导致通信缓慢的原因。
数据传输速率
这通常包括衡量从该站点到网络中其他站点的大量数据传输。你可以使用 Wireshark 的捕获摘要和图形功能(在第五章中展示)来确定传输速率和连接的一致性。这可能是你拥有的最重要的站点基线。每当任何进入或离开网络段的连接看起来很慢时,你可以执行与你的基线相同的数据传输并进行比较。这样你可以判断连接是否真的很慢,甚至可能帮助你找到导致慢速的区域。
主机基线
你可能不需要为网络中的每个主机设置基线。主机基线应仅在高流量或关键任务服务器上执行。基本上,如果一个缓慢的服务器会导致管理层打来愤怒的电话,那么你应该为该主机设置基线。
主机基线的组成部分包括以下内容:
使用中的协议
这个基线提供了一个很好的机会,可以在捕获主机流量时使用协议层次统计窗口。之后,你可以将其与基线进行比较,找出是否有正常存在的协议丢失,或新协议已出现在主机上。你还可以用它来根据协议发现异常大的某些类型的流量。
空闲/繁忙流量
这个基线仅包括在高峰和非高峰时间段的正常操作流量的通用捕获。了解在一天中不同时间连接数和这些连接使用的带宽量,将帮助你判断缓慢是否由于用户负载或其他问题引起。
启动/关闭
要获得这个基线,你需要创建一个捕获,记录主机启动和关闭序列期间生成的流量。如果计算机拒绝启动、拒绝关闭,或在任何一个序列中表现出异常的慢速,你可以利用这个基线来判断原因是否与网络相关。
认证序列
获取这个基线需要捕获所有服务认证过程的流量。认证是服务常常变慢的一个领域。基线使你能够判断认证是否是造成通信缓慢的原因。
关联/依赖关系
这个基线由一个较长时间的捕获组成,用于确定该主机依赖于哪些其他主机(以及哪些主机依赖于它)。你可以使用会话窗口(统计 ▶ 会话)查看这些关联和依赖关系。例如,一个 SQL 服务器主机,网络中的一个 Web 服务器依赖于它。我们并不总是意识到主机之间潜在的依赖关系,因此可以通过主机基线来识别这些依赖关系。接下来,你可以判断是否由于某个故障或高延迟的依赖关系导致主机无法正常工作。
应用程序基准
最终的网络基准类别是应用程序基准。这个基准应该在所有业务关键的网络应用程序上执行。
以下是应用程序基准的组成部分:
使用的协议
再次,对于这个基准,使用 Wireshark 中的协议层次统计窗口,这次是在捕获来自运行应用程序的主机的流量时进行。之后,你可以与这个列表进行比较,以查看应用程序依赖的协议是否出现故障,或根本无法工作。
启动/关闭
该基准包括在应用程序启动和关闭序列期间生成的流量捕获。如果应用程序在任何一个序列中拒绝启动或异常缓慢,可以使用该基准来确定问题原因。
关联/依赖
这个基准需要进行较长时间的捕获,可以利用会话窗口来确定该应用程序依赖于哪些其他主机和应用程序。我们并不总是意识到应用程序之间的潜在依赖关系,因此可以使用这个基准来确定这些依赖关系。然后,你可以确定应用程序是否因某个故障或高延迟的依赖而无法正常运行。
数据传输速率
你可以使用 Wireshark 的捕获总结和图形功能来确定应用程序服务器在正常操作期间的传输速率和连接一致性。每当应用程序报告为缓慢时,你可以使用这个基准来确定是否是由于高利用率或高用户负载导致的问题。
基准的额外说明
在创建网络基准时,还有一些其他要点需要记住:
• 在创建基准时,每个基准至少要捕获三次:一次在低流量时段(清晨),一次在高流量时段(下午),一次在无流量时段(深夜)。
• 在可能的情况下,避免直接从你正在基准化的主机上捕获数据。在高流量时段这样做可能会增加设备的负载,影响其性能,并导致丢包,使得基准无效。
• 你的基准将包含一些关于你网络的非常敏感的信息,因此要确保对其进行保护。将其存储在一个安全的地方,只有合适的人才能访问。但同时,也要确保它随时可用,以便在需要时使用。可以考虑将其存储在 USB 闪存驱动器或加密分区中。
• 保留所有与基准相关的.pcap和.pcapng文件,并创建一份常用值的备忘单,例如关联关系或平均数据传输速率。
最终思考
本章重点讨论了慢网络故障排除。我们介绍了一些 TCP 中更有用的可靠性检测和恢复功能,演示了如何定位网络通信中的高延迟来源,并讨论了网络基线及其一些组成部分的重要性。运用本文中讨论的技术,以及 Wireshark 的图形和分析功能,你应该能够做好充分准备,当接到抱怨网络慢的电话时进行故障排除。
第十二章:安全的报文分析

尽管本书的大部分内容侧重于使用报文分析进行网络故障排除,但相当一部分实际的报文分析是出于安全目的进行的。例如,入侵分析师可能会审查来自潜在入侵者的网络流量,或者取证调查员可能会尝试确定在被攻陷主机上恶意软件感染的程度。
在调查安全事件时进行报文分析总是一个具有挑战性的场景,因为它涉及到一个攻击者控制的未知设备。你无法走到攻击者的工作区提问或基准测试他们的正常流量;你只能依赖于你可以捕获到的他们的系统和你系统之间的交互。幸运的是,为了远程入侵你的系统,攻击者必须以某种形式与网络互动。当然,他们也知道这一点,所以他们不缺少用来混淆技术的手段。
在本章中,我们将从安全实践者的角度出发,检查系统在网络层面的不同方面被攻陷的情况。我们将讨论网络侦察、恶意流量重定向和常见的恶意软件技术。在某些情况下,我们将扮演入侵分析师的角色,根据入侵检测系统(IDS)发出的警报分析流量。阅读本章将为你提供关于网络安全的深刻见解,即使你目前不在一个专注于安全的角色中,这些知识也可能至关重要。
侦察
攻击者的第一步通常是对目标系统进行深入的研究。这个步骤通常被称为信息收集,通常通过各种公开可用的资源来完成,例如目标公司的官方网站或谷歌。一旦完成这项研究,攻击者通常会开始扫描他们目标的 IP 地址(或 DNS 名称),以寻找开放的端口或正在运行的服务。
扫描可以让攻击者判断目标是否存活且可达。例如,考虑一个场景,其中银行劫匪计划从城市最大的银行——位于 123 Main Street 的银行——进行盗窃。他们花了几周时间策划精密的抢劫计划,结果一到地址就发现银行已经搬到了 555 Vine Street。更糟糕的是,假设这些劫匪计划在正常营业时间进入银行,打算从金库里偷东西,结果一到银行才发现当天银行关门了。无论是抢劫银行还是攻击网络,确保目标存活且可达是第一道难关。
扫描还可以告诉攻击者目标在哪些端口上进行监听。回到我们的银行抢劫者比喻,假设抢劫者来到银行,完全不了解大楼的物理布局。他们根本不知道如何进入金库,因为他们不知道银行物理安全的薄弱环节。
在本节中,我们将讨论一些常见的扫描技术,用于识别网络上的主机、开放端口和漏洞。
注意
到目前为止,本书提到的连接双方分别是 发送方 和 接收方 ,或是 客户端 和 服务器。本章则将通信的每一方称为 攻击者 或 目标*。
SYN 扫描
synscan.pcapng
针对系统进行的常见扫描类型之一是 TCP SYN 扫描,也称为 隐身扫描 或 半开放扫描。SYN 扫描之所以是最常见的类型,原因有几个:
• 它非常快速且可靠。
• 它在所有平台上都非常准确,无论 TCP 堆栈实现如何。
• 它比其他扫描技术更不容易被察觉。
TCP SYN 扫描依赖于三次握手过程来确定目标主机上哪些端口是开放的。攻击者向目标的多个端口发送一个 TCP SYN 数据包,仿佛是在尝试为正常通信在这些端口上建立一个通道。一旦目标收到这个数据包,可能会发生几种不同的情况,如图 12-1 所示。

图 12-1:TCP SYN 扫描的可能结果
如果目标机器上的某个服务正在监听接收 SYN 数据包的端口,它将通过一个 TCP SYN/ACK 数据包回应攻击者,这是 TCP 三次握手的第二部分。此时,攻击者就知道该端口是开放的,并且有服务在监听。正常情况下,最终会发送一个 TCP ACK 数据包来完成连接的握手。然而,在这种情况下,攻击者并不希望发生这种情况,因为此时他们不会与主机进一步通信,因此攻击者不会尝试完成 TCP 握手。
如果在扫描的端口上没有服务在监听,攻击者将不会收到 SYN/ACK 数据包。根据目标操作系统的配置,攻击者可能会收到一个 RST 数据包,表示该端口已关闭。或者,攻击者可能根本没有收到任何响应。没有响应可能意味着该端口被中间设备(如防火墙或主机本身)过滤。另一方面,也有可能是响应在传输过程中丢失。因此,虽然这种结果通常表示端口已关闭,但最终仍无法得出结论。
文件 synscan.pcapng 提供了一个使用 Nmap 工具执行 SYN 扫描的良好示例。Nmap 是一款功能强大的网络扫描应用程序,由 Gordon “Fyodor” Lyon 开发。它几乎可以执行你能想象的任何类型的扫描。你可以从 www.nmap.com/download.html 免费下载 Nmap。
我们的示例捕获包含大约 2,000 个数据包,这告诉我们这个扫描的规模是合理的。确定此类扫描范围的最佳方法之一是查看对话窗口,如图 12-2 所示。在那里,你应该只看到一条 IPv4 对话 ➊,它是攻击者(172.16.0.8)与目标(64.13.134.52)之间的通信。你还会看到这两个主机之间有 1,994 个 TCP 对话 ➋——基本上每个涉及通信的端口配对都会生成一个新的对话。

图 12-2:对话窗口显示了各种 TCP 通信。
扫描进行得非常快,所以滚动查看捕获文件并不是找到每个初始 SYN 数据包响应的最佳方式。在收到原始数据包的响应之前,可能会发送几个其他数据包。幸运的是,我们可以创建过滤器来帮助我们找到正确的流量。
使用过滤器进行 SYN 扫描
作为过滤的示例,我们来看捕获中的第一个数据包,它是发送到目标端口 443(HTTPS)的 SYN 数据包。为了查看是否有响应此数据包的流量,我们可以创建一个过滤器,显示所有往返于端口 443 的流量。以下是如何快速完成此操作:
-
选择捕获文件中的第一个数据包。
-
展开数据包详细信息窗格中的 TCP 头部。
-
右键单击目标端口字段,选择准备为过滤器,然后点击选定。
-
这将为所有目标端口为 443 的数据包在过滤器对话框中设置一个过滤器。现在,因为我们还需要所有源端口为 443 的数据包,点击屏幕顶部的过滤器对话框,并删除过滤器中的 dst 部分。
结果过滤器将显示两个数据包,它们都是从攻击者到目标发送的 TCP SYN 数据包,如图 12-3 所示。

图 12-3:使用 SYN 数据包建立连接的两次尝试
注意
在本节中,数据包使用自上一个显示的数据包以来的秒数格式进行显示。
由于这两个数据包没有收到响应,可能是响应被目标主机或中间设备过滤,或者端口已关闭。最终,对端口 443 的扫描结果是不确定的。
我们可以尝试对另一个数据包使用相同的技术,看是否得到不同的结果。为此,清除之前的过滤器并选择列表中的数据包 9。这是发送到端口 53 的 SYN 数据包,通常与 DNS 相关。使用前述步骤中的方法,或者通过修改最后一个过滤器,创建一个过滤器,显示所有 TCP 端口 53 的流量。当你应用这个过滤器时,你应该看到五个数据包,如图 12-4 所示。

图 12-4:表示端口开放的五个数据包
这些数据包中的第一个是我们在捕获开始时选择的 SYN(数据包 9)。第二个是目标的响应。这是一个 TCP SYN/ACK——在建立三次握手时预期的响应。在正常情况下,下一个数据包将是发送初始 SYN 的主机的 ACK。然而,在这种情况下,我们的攻击者并不希望完成连接,因此没有发送响应。结果,目标在放弃之前重新传输了三次 SYN/ACK。由于在尝试与端口 53 上的主机通信时收到了 SYN/ACK 响应,因此可以安全地假设该端口上有服务在监听。
让我们再重复这个过程一次,针对数据包 13。这是发送到端口 113 的 SYN 数据包,通常与 Ident 协议相关,常用于 IRC 身份验证和认证服务。如果对这个数据包中列出的端口应用相同类型的过滤器,你将看到四个数据包,如图 12-5 所示。

图 12-5:一个 SYN 后跟一个 RST,表示端口关闭
第一个数据包是初始 SYN,紧接着是目标的 RST。这表示目标没有在目标端口上接受连接,并且很可能没有服务在该端口上运行。
识别开放和关闭的端口
现在你理解了 SYN 扫描可以引发的不同类型的响应,你将希望找到一种快速的方法来识别哪些端口是开放的,哪些是关闭的。答案再次存在于会话窗口中。在这个窗口中,你可以通过点击“数据包”列标题,按数据包编号对 TCP 会话进行排序,直到箭头指向下方,如图 12-6 所示。

图 12-6:使用会话窗口查找开放端口
三个扫描端口在它们的每个会话中包含五个数据包➊。我们知道端口 53、80 和 22 是开放的,因为这五个数据包代表了初始 SYN、相应的 SYN/ACK 以及目标的重传 SYN/ACK。
对五个端口,只有两个数据包参与了通信➋。第一个是初始 SYN,第二个是目标的 RST。这些结果表明端口 113、25、31337、113 和 70 是关闭的。
对话窗口中的剩余条目仅包括一个数据包,意味着目标主机从未对初始的 SYN 做出响应。这些端口很可能是关闭的,但我们不确定。
这种通过计数数据包的技术在这个主机上有效,但并不适用于你可能扫描的所有主机,因此你不应完全依赖它。相反,应该专注于学习什么是正常的刺激和响应,以及对正常刺激的异常响应可能意味着什么。
操作系统指纹识别
攻击者非常重视了解目标操作系统的情况。了解操作系统有助于攻击者正确配置所有攻击方法,以适应该系统。它还允许攻击者知道目标文件系统中某些关键文件和目录的位置,如果他们成功访问系统的话。
操作系统指纹识别是指一组技术,用于在没有物理访问权限的情况下确定系统上运行的操作系统。有两种类型的操作系统指纹识别:被动和主动。
被动指纹识别
passiveosfinger printing.pcapng
使用被动指纹识别,你可以检查从目标发送的某些数据包字段,以确定正在使用的操作系统。该技术被认为是被动的,因为你只监听目标主机发送的数据包,而不是主动向主机发送任何数据包。这种类型的操作系统指纹识别非常适合攻击者,因为它使他们能够保持隐蔽。
话虽如此,我们如何仅凭目标主机发送的数据包来确定其操作系统呢?这项技术之所以可能,是因为协议 RFC 中定义的规范没有标准化的值。尽管 TCP、UDP 和 IP 头中的各种字段非常具体,但通常并未为每个字段定义默认值。这意味着每个操作系统中的 TCP/IP 堆栈实现必须为这些字段定义自己的默认值。表 12-1 列出了部分常见字段及其默认值,这些默认值可以用来将它们与不同的操作系统关联。请记住,这些值可能会随着新的操作系统版本发布而发生变化。
表 12-1: 常见的被动指纹识别值
| 协议头 | 字段 | 默认值 | 平台 |
|---|---|---|---|
| IP | 初始生存时间 | 64 | NMap, BSD, OS X, Linux |
| 128 | Novell, Windows | ||
| 255 | Cisco IOS, Palm OS, Solaris | ||
| IP | 不分段标志 | 设置 | BSD, OS X, Linux, Novell, Windows, Palm OS, Solaris |
| 未设置 | Nmap, Cisco IOS | ||
| TCP | 最大报文段大小 | 0 | Nmap |
| 1440–1460 | Windows, Novell | ||
| 1460 | BSD, OS X, Linux, Solaris | ||
| TCP | 窗口大小 | 1024–4096 | Nmap |
| 65535 | BSD, OS X | ||
| 变量 | Linux | ||
| 16384 | Novell | ||
| 4128 | Cisco IOS | ||
| 24820 | Solaris | ||
| 可变 | Windows | ||
| TCP | SackOK | 设置 | Linux, Windows, OS X, OpenBSD |
| 未设置 | Nmap, FreeBSD, Novell, Cisco IOS, Solaris |
存储在文件passiveosfingerprinting.pcapng中的数据包是这种技术的绝佳示例。文件中有两个数据包,两个都是发送到端口 80 的 TCP SYN 数据包,但它们来自不同的主机。仅使用这些数据包中包含的值,并参考表 12-1,我们应该能够确定每个主机上使用的操作系统架构。每个数据包的详细信息见图 12-7。
使用表 12-1 作为参考,我们可以创建表 12-2,它是这些数据包中相关字段的细分。
表 12-2: 操作系统指纹识别数据包细分
| 协议头 | 字段 | 数据包 1 值 | 数据包 2 值 |
|---|---|---|---|
| IP | 初始生存时间 | 128 | 64 |
| IP | 不分片标志 | 设置 | 设置 |
| TCP | 最大段大小 | 1,440 字节 | 1,460 字节 |
| TCP | 窗口大小 | 64,240 字节 | 2,920 字节 |
| TCP | SackOK | 设置 | 设置 |
基于这些值,我们可以得出结论,数据包 1 很可能是由运行 Windows 的设备发送的,而数据包 2 很可能是由运行 Linux 的设备发送的。
请记住,表 12-1 中列出的常见被动指纹识别标识字段并非详尽无遗。还有许多特殊情况可能导致这些预期值的偏差。因此,你不能完全依赖被动操作系统指纹识别得到的结果。

图 12-7:这些数据包可以告诉我们它们是从哪个操作系统发送的。
注意
在许多情况下,攻击者依赖自动化工具来被动识别目标的操作系统。使用操作系统指纹识别技术的一个工具是 p0f。该工具分析数据包捕获中的相关字段并输出疑似的操作系统。通过使用像 p0f 这样的工具,你不仅可以获取操作系统架构,有时甚至可以得到操作系统的版本或补丁级别。你可以从 lcamtuf.coredump.cx/p0f.shtml 下载 p0f。
主动指纹识别
activeosfingerprinting.pcapng
当被动监控流量未能获得预期结果时,可能需要采取更直接的方法——主动指纹识别。在这种方法中,攻击者主动向目标发送特别构造的数据包,以引发回复,从而揭示目标机器上的操作系统。当然,由于这种方法涉及直接与目标通信,因此并不隐蔽,但它可以非常有效。
文件activeosfingerprinting.pcapng包含了一个使用 Nmap 扫描工具发起的主动操作系统指纹识别扫描的示例。该文件中的多个数据包是 Nmap 发送的不同探测包的结果,旨在引发响应,从而识别操作系统。Nmap 会记录这些探测包的响应,并构建指纹,随后与数据库中的值进行比对,以做出判断。
注意
Nmap 用于主动指纹识别操作系统的技术相当复杂。要了解 Nmap 如何执行主动操作系统指纹识别,请阅读该工具作者 Gordon “Fyodor” Lyon 的权威指南,《Nmap 网络扫描》(2008)。
流量操控
本书中我一直尝试展示的一个关键点是,通过分析正确的数据包,你可以了解一个系统或其用户的许多信息。因此,攻击者通常会自己捕获这些数据包,这一点并不奇怪。通过分析系统生成的数据包,攻击者可以了解操作系统、使用的应用程序、身份验证凭证等等。
本节中,我们将讨论两种数据包级别的技术:攻击者如何利用 ARP 缓存中毒拦截和捕获目标流量,以及他们如何拦截 HTTP cookies 进行会话劫持攻击。
ARP 缓存中毒
arppoison.pcapng
在第七章中,我们讨论了 ARP 协议如何允许设备在网络内部将 IP 地址映射到 MAC 地址;在第二章中,我们讨论了 ARP 缓存中毒如何成为一个有用的技术,可以帮助我们接入网络并拦截需要分析的主机流量。当用于合法目的时,ARP 缓存中毒对故障排除非常有帮助。然而,当该技术被用于恶意目的时,它将成为一种致命的中间人攻击 (MITM)。
在 MITM 攻击中,攻击者会重定向两个主机之间的流量,以便拦截或修改传输中的数据。MITM 攻击有很多种形式,包括 DNS 欺骗和 SSL 劫持。在 ARP 缓存中毒中,特殊构造的 ARP 数据包使得两台主机误认为它们在彼此之间通信,实际上它们是在与第三方通信,第三方充当中介转发数据包。通过这种方式,协议的正常功能被不正当使用,进而被用作恶意目的。
文件arppoison.pcapng包含了一个 ARP 缓存中毒的示例。当你打开它时,你会发现这些流量乍看之下是正常的。然而,如果你跟踪数据包,你会看到我们的目标 172.16.0.107 正在浏览 Google 并进行搜索。由于这次搜索,产生了大量的 HTTP 流量,并夹杂了一些 DNS 查询。
我们知道,ARP 缓存中毒是一种发生在第二层的技术,因此如果我们只是随便浏览数据包列表窗格,可能很难看到任何恶意行为。为了帮助我们识别这些,我们将在数据包列表窗格中添加几个列,如下所示:
-
选择编辑 ▶ 首选项。
-
点击首选项窗口左侧的列。
-
点击加号(+)按钮以添加一个新列。
-
在标题区域,输入源 MAC 并按 ENTER 键。
-
在类型下拉列表中,选择Hw src addr (resolved)。
-
点击新添加的条目并拖动它,使其紧接在源列后面。
-
点击加号(+)按钮以添加一个新列。
-
在标题区域,输入目标 MAC 并按 ENTER 键。
-
在类型下拉列表中,选择Hw dest addr (resolved)。
-
点击新添加的条目并拖动它,使其紧接在目标列后面。
-
点击确定以应用更改。
当你完成这些步骤后,屏幕应该会像图 12-8 所示。此时,你应该有两列额外显示数据包的源 MAC 地址和目标 MAC 地址。

图 12-8:添加了源和目标硬件地址的新列配置屏幕
如果你仍然开启了 MAC 名称解析,你应该能看到通信设备的 MAC 地址,标示出 Dell 和 Cisco 硬件。记住这一点非常重要,因为当我们浏览捕获的数据时,会看到在第 54 个数据包处发生了变化,此时我们看到 Dell 主机(我们的目标)与新引入的 HP 主机(攻击者)之间发生了某些奇怪的 ARP 流量,如图 12-9 所示。

图 12-9:Dell 设备与 HP 设备之间的奇怪 ARP 流量
在继续操作之前,请注意此通信中涉及的端点,这些端点列在表 12-3 中。
表 12-3: 正在监控的端点
| 角色 | 设备类型 | IP 地址 | MAC 地址 |
|---|---|---|---|
| 目标 | Dell | 172.16.0.107 | 00:21:70:c0:56:f0 |
| 路由器 | Cisco | 172.16.0.1 | 00:26:0b:31:07:33 |
| 攻击者 | HP | 未知 | 00:25:b3:bf:91:ee |
但是,是什么让这段流量显得奇怪呢?回顾我们在第七章中关于 ARP 的讨论,ARP 数据包有两种主要类型:请求和响应。请求数据包作为广播发送到网络中的所有主机,以便找到与特定 IP 地址关联的 MAC 地址。然后,回复请求设备的主机发送一个单播数据包作为响应。根据这些背景信息,我们可以识别出此通信序列中的一些异常,参考图 12-9。
首先,数据包 54 是一个 ARP 请求,由攻击者(MAC 地址 00:25:b3:bf:91:ee)作为单播数据包直接发送到目标(MAC 地址 00:21:70:c0:56:f0)➊。这种类型的请求应该广播给网络上的所有主机,但这个请求仅仅指向了目标。同时,注意到尽管这个数据包是由攻击者发送,并且在 ARP 头中包含了攻击者的 MAC 地址,但它列出了路由器的 IP 地址,而不是攻击者自己的。
紧接着,目标向攻击者回应了一个包含其 MAC 地址信息的数据包➋。真正的“巫术”发生在数据包 56 中,攻击者向目标发送了一个未经请求的 ARP 回复,告诉目标 172.16.0.1 位于其 MAC 地址 00:25:b3:bf:91:ee 处➌。问题是,MAC 地址 172.16.0.1 并不是 00:25:b3:bf:91:ee,而是 00:26:0b:31:07:33。我们之所以知道这一点,是因为我们在之前的数据包捕获中看到了路由器与目标之间的通信。由于 ARP 协议本身不安全(它接受未经请求的 ARP 表更新),目标现在会把本应发送给路由器的流量发送给攻击者。
注意
由于这个数据包捕获来自目标的机器,因此你实际上并没有看到整个情况。为了让这次攻击生效,攻击者必须向路由器发送相同的包序列,以让路由器认为攻击者实际上就是目标,但我们需要从路由器(或攻击者)获取另一个数据包捕获,才能看到那些数据包。
一旦目标和路由器都被欺骗,二者之间的通信就会通过攻击者进行传输,如图 12-10 所示。

图 12-10:作为 MITM 攻击的 ARP 缓存中毒
数据包 57 确认了此次攻击的成功。通过将这个数据包与神秘 ARP 流量之前发送的一个数据包进行对比,比如数据包 40(见图 12-11),你会发现远程服务器(Google)的 IP 地址保持不变➋,但目标的 MAC 地址发生了变化➊。MAC 地址的变化告诉我们,流量现在正在通过攻击者进行路由,直到到达路由器。
由于此攻击非常隐蔽,因此很难检测。为了发现它,通常需要借助专门配置的 IDS(入侵检测系统),或者是运行在设备上的软件,用于检测 ARP 表条目的突变。由于你很可能会使用 ARP 缓存中毒来捕获你正在分析的网络上的数据包,因此了解这种技术如何被用于攻击你是很重要的。

图 12-11:目标 MAC 地址的变化表明此次攻击成功。
会话劫持
sessionhijacking.pcapng
现在你已经知道了 ARP 缓存中毒可以被恶意利用,我想展示一种可以利用它的技术:会话劫持。在会话劫持中,攻击者获取一个 HTTP 会话 cookie,稍后我们将学习它,并用它冒充另一个用户。为了实现这一点,攻击者可以利用 ARP 缓存中毒来拦截目标的流量并找到相关的会话 cookie 信息。然后,攻击者可以使用这些信息以目标用户的身份访问目标 web 应用程序。
本场景从文件 sessionhijacking.pcapng 开始。该捕获文件包含了一个目标(172.16.16.164)与一个 web 应用程序(172.16.16.181)之间的通信流量。在目标不知情的情况下,他们已经成为攻击者(172.16.16.154)的受害者,攻击者正在积极拦截他们的通信。这些数据包是从 web 服务器的角度收集的,这很可能是防御者在针对其服务器基础设施实施会话劫持攻击时所拥有的视角。
注意
这里访问的 web 应用程序名为 Damn Vulnerable Web Application (DVWA)。它故意存在许多类型的漏洞,常被用作教学工具。如果你想了解更多关于 web 应用攻击的信息或分析与这些攻击相关的数据包,可以在 www.dvwa.co.uk/ 了解更多关于 DVWA 的内容。
该捕获中的流量主要包含两次对话。第一次是目标与 web 服务器之间的通信,可以通过过滤器 ip.addr == 172.16.16.164 && ip.addr == 172.16.16.181 来隔离。这种通信表示正常的 web 浏览流量,没有特别之处。特别值得关注的是请求中的 cookie 值。例如,如果你查看第 14 包中的 GET 请求,你会在数据包详细信息窗口中找到 cookie,如 图 12-12 所示。在这种情况下,cookie 通过一个 PHPSESSID 值 ncobrqrb7fj2a2sinddtk567q4 ➊ 来标识会话 ID。

图 12-12:查看目标的会话 cookie
网站使用 cookies 来维持对单独主机的会话识别。当新访客访问网站时,系统会为其分配一个唯一的会话 ID(即 PHPSESSID)。为了进行身份验证,许多应用会等待具有会话 ID 的用户成功登录应用后,才会创建一个数据库记录,识别该 ID 为已验证会话的代表。任何拥有该 ID 的用户都可以使用该身份验证访问应用。当然,开发者通常认为只有单一用户拥有特定的 ID,因为这些 ID 是唯一生成的。然而,这种处理会话 ID 的方法并不安全,因为它允许恶意用户窃取其他用户的 ID 并冒充他们。虽然有方法可以防止会话劫持技术,但许多网站,包括 DVWA,仍然容易受到攻击。
目标并没有意识到他们的流量正被攻击者拦截,或者攻击者已经获取到会话 cookie,如图 12-12 所示。攻击者所要做的,就是使用该 cookie 值与 Web 服务器进行通信。这项任务可以通过某些类型的代理服务器来完成,但使用像 Chrome 的 Cookie 管理器这样的浏览器插件会更轻松。通过这个插件,攻击者可以指定从目标流量中获取的 PHPSESSID 值,如图 12-13 所示。

图 12-13:使用 Cookie 管理器插件模拟目标身份
如果你清除之前应用于捕获文件的过滤器并开始向下滚动,最终会看到攻击者的 IP 地址与 Web 服务器进行通信。你可以通过过滤器 ip.addr == 172.16.16.154 && ip.addr == 172.16.16.181 来限制视图,只显示这些通信。
在我们进一步探讨之前,先在数据包列表窗格中添加一列来显示 cookie 值。如果你在上一节的 ARP 缓存投毒部分已经添加了列,应该先移除这些列。然后,按照 ARP 缓存投毒部分的说明,基于字段名 http.cookie_pair 添加新的自定义列。一旦添加完成,将该列放置在目标字段后面。你的屏幕应该如图 12-14 所示。

图 12-14:配置列以调查会话劫持
配置好新的列后,修改显示过滤器,只显示 HTTP 请求,因为 TCP 通信在这里没有用处。新的过滤器是 (ip.addr172.16.16.154 && ip.addr172.16.16.181) && (http.request.method || http.response.code)。结果包如图 12-15 所示。

图 12-15:攻击者冒充目标用户
现在你正在查看攻击者与服务器之间的通信。在前四个数据包中,攻击者请求 /dvwa/ 目录 ➊,并收到 302 响应代码,这是 web 服务器用来将访客重定向到不同 URL 的正常方法。在这种情况下,攻击者被重定向到了登录页面 /dvwa/login.php ➋。攻击者的机器请求了登录页面 ➌,并成功返回 ➍。这两个请求都使用了会话 ID lup70ajeuodkrhrvbmsjtgrd71。
随后,发出了新的请求来访问 /dvwa/ 目录,但这次请注意不同的会话 ID ➎。会话 ID 现在是 ncobrqrb7fj2a2sinddtk567q4,与目标先前使用的相同。这表明攻击者已经操控了流量,使用了被盗的 ID。请求没有被重定向到登录页面,而是返回了 HTTP 200 状态码,并且页面以目标认证后的样子被呈现 ➏。攻击者使用目标的 ID 浏览了另一个页面 dvwa/setup.php ➐,该页面也成功返回 ➑。攻击者像目标一样浏览 DVWA 网站,而无需知道目标的用户名或密码。
这只是一个例子,展示了攻击者如何将数据包分析转化为攻击工具。一般来说,可以安全地假设,如果攻击者能够看到与你的通信相关的数据包,那么就有可能导致某种类型的恶意活动。这也是安全专业人士主张通过加密保护传输数据的原因之一。
恶意软件
尽管完全合法的软件也可以用于恶意目的,恶意软件通常是指专门为了恶意意图而编写的代码。恶意软件可以有多种形态,包括自我传播的蠕虫和伪装成合法软件的特洛伊木马。从网络防御者的角度来看,大多数恶意软件在被捕获和分析之前是无法发现和未知的。这个分析过程涉及多个步骤,其中一个步骤是专注于恶意软件的网络通信模式的行为分析。在某些情况下,分析发生在法医恶意软件反向工程实验室中,但更多时候,它发生在野外,当安全分析师发现他们的网络中某个设备被感染时。
在这一部分,我们将通过数据包观察几个真实的恶意软件及其行为示例。
奥罗拉行动
aurora.pcapng
2010 年 1 月,发现奥罗拉行动利用了 Internet Explorer 中一个当时尚未被发现的漏洞。这个漏洞使得攻击者能够远程控制 Google 等公司内部的目标机器。
为了执行这些恶意代码,用户只需访问一个使用易受攻击版本的 Internet Explorer 的网页。攻击者随后便能够直接访问用户的机器,并且拥有与已登录用户相同的权限。鱼叉式钓鱼攻击通过向受害者发送设计用来诱使他们点击链接访问恶意网站的电子邮件来吸引目标。
在 Aurora 案例中,我们从目标用户点击鱼叉式钓鱼邮件中的链接开始跟踪此事件。生成的数据包包含在文件aurora.pcapng中。
该捕获过程开始于目标(192.168.100.206)与攻击者(192.168.100.202)之间的三次握手。初始连接是通过 80 端口,这让我们认为这是 HTTP 流量。这个假设在第四个数据包中得到了证实,该数据包是一个针对/info的 HTTP GET请求 ➊,如图 12-16 所示。
如图 12-17 所示,攻击者的机器确认收到了GET请求,并在数据包 6 ➊中报告了 302(暂时移动)响应代码,这是常用的重定向浏览器到另一个页面的状态码,正如本例所示。除了 302 响应代码外,Location 字段指定了位置/info?rFfWELUjLJHpP ➋。

图 12-16:目标发起了对 /info 的GET请求。

图 12-17:客户端浏览器通过此数据包被重定向。
收到 HTTP 302 数据包后,客户端发起了对/info?rFfWELUjLJHpP URL 的另一个GET请求,该请求在数据包 7 中出现,并且在数据包 8 中收到 ACK。接着,下一些数据包代表着攻击者向目标传输的数据。要查看这些数据,右键点击流中的一个数据包,比如数据包 9,然后选择跟踪 ▶ TCP 流。在此流输出中,我们可以看到最初的GET请求、302 重定向以及第二个GET请求,如图 12-18 所示。
接下来,事情开始变得非常奇怪。攻击者用一些看起来非常奇怪的内容响应了GET请求,其中的第一部分如图 12-19 所示。

图 12-18:数据流被传输到客户端

图 12-19:<script>标签内的这段混淆内容似乎经过了编码处理。
该内容看起来是一串随机的数字和字母,位于 <script> 标签内 ➊。<script> 标签用于 HTML 中,表示使用一种高级的客户端脚本语言,其代码在 HTTP 客户端上执行。在这个标签内,通常可以看到各种脚本语句。但这里的乱码表示内容可能已经被编码,以隐藏其真实信息。由于我们知道这是攻击流量,可以推测这段被混淆的文本包含了用于利用易受攻击服务的十六进制填充和 Shellcode。
注意
脚本混淆是恶意软件常用的一种技术,用于规避检测并隐藏恶意内容。虽然本书不涉及脚本去混淆,但如果你继续研究恶意软件通信,这将是你会掌握的技能。许多经验丰富的恶意软件分析师可以通过快速的视觉检查立刻识别出恶意脚本。如果你想挑战自己,试着手动去混淆本例中找到的脚本。
在攻击者发送的第二部分内容中,如 图 12-20 所示,我们最终看到了可以读取的文本。即使没有广泛的编程知识,我们也能看出,这段文本似乎基于一些变量进行字符串解析。这是 </script> 标签关闭之前的最后一段文本。

图 12-20:这部分从服务器发送的内容包含可读文本和一个可疑的 iframe。
从攻击者发送到客户端的最后一部分数据,如 图 12-20 所示,分为两部分。第一部分是 <span id="vhQYFCtoDnOzUOuxAflDS zVMIHYhjJojAOCHNZtQdlxSPFUeEthCGdRtiIY"> 部分 ➊。第二部分,包含在 <span></span> 标签内,是 <iframe src="/infowTVeeGDYJWNfsrdrvXiYApnuPoC MjRrSZuKtbVgwuZCXwxKjtEclbPuJPPctcflhsttMRrSyxl.gif" onload="WisgEgTNEfaONekE qaMyAUALLMYW(event)" /> ➋。再一次,这段内容可能是恶意活动的迹象,原因是其中有异常长且随机的无法读取、可能已混淆的文本。
包含在 <span> 标签内的部分代码是一个 iframe,这是攻击者常用的一种方法,用来将额外的意外内容嵌入到 HTML 页面中。<iframe> 标签创建了一个内联框架,用户通常无法察觉。在这种情况下,<iframe> 标签引用了一个命名奇怪的 GIF 文件。如 图 12-21 所示,当目标的浏览器看到这个文件的引用时,它会在第 21 包中发出一个 GET 请求 ➊,然后 GIF 文件会紧接着被发送 ➋。

图 12-21:iframe 中指定的 GIF 被目标请求并下载。
此捕获中最奇怪的部分发生在数据包 25,当时目标发起了一个回连接到攻击者的端口 4321。查看来自数据包详细信息窗格的这第二个通信流没有提供太多信息,因此我们将再次查看 TCP 流,以便更清晰地了解正在传输的数据。 图 12-22 显示了跟踪 TCP 流的窗口输出。
在此显示中,我们看到一些应该立即引起警报的内容:一个 Windows 命令行 ➊。此命令行从目标发送到服务器,表明攻击者的漏洞利用尝试成功,并且有效负载已被投放。一旦漏洞被启动,客户端便将命令行传回给攻击者。在此捕获中,我们甚至能看到攻击者通过输入 dir 命令 ➋ 来查看目标机器上的目录列表 ➌。
假设漏洞已经利用并感染了以管理员身份运行的进程,或者已迁移至其中,攻击者几乎可以对目标机器做任何他们想做的事情。仅需点击一下,在几秒钟内,目标就将其计算机的完全控制权交给了攻击者。
像这样的漏洞利用通常会被编码以在传输过程中变得无法识别,以防止被网络 IDS 拦截。因此,在没有事先了解此漏洞或漏洞代码样本的情况下,可能很难确定目标系统上发生了什么,除非进行进一步的分析。幸运的是,我们能够从此数据包捕获中找出一些恶意代码的明显迹象。这包括 <script> 标签中的混淆文本、奇怪的 iframe 以及以明文显示的命令行。

图 12-22:攻击者通过此连接与命令行进行交互。
以下是 Aurora 漏洞在这里如何工作的总结:
• 目标接收到攻击者发送的看似合法的电子邮件,点击其中的链接,并向攻击者的恶意站点发送 GET 请求。
• 攻击者的 Web 服务器向目标发出 302 重定向,目标的浏览器自动向重定向的 URL 发出 GET 请求。
• 攻击者的 Web 服务器向客户端传输一个包含混淆 JavaScript 代码的网页,代码中包含一个漏洞利用程序和一个包含指向 GIF 图像的链接的 iframe,后者被请求。
• 之前传输的 JavaScript 代码在目标的浏览器中渲染页面时被去混淆,并在他们的机器上执行,利用了 Internet Explorer 中的漏洞。
• 一旦漏洞被利用,隐藏在混淆代码中的有效负载将被执行,打开一个新的会话,从目标连接到攻击者的端口 4321。
• 从有效负载中生成命令行并返回给攻击者,以便他们与其交互。
从防御者的角度来看,我们可以使用这个捕获文件为我们的 IDS(入侵检测系统)创建一个签名,帮助检测未来可能发生的类似攻击。例如,我们可以过滤捕获文件中的一个未加密部分,比如<script>标签中加密文本结尾的明文代码。另一个思路是为所有带有 302 重定向到 URL 中含有info的站点的 HTTP 流量编写签名。这个签名需要进行一些额外的调整才能在生产环境中可行,但它是一个不错的开始。当然,值得记住的是,签名是可以被绕过的。如果攻击者只是更改了我们观察到的几个字符串,或者通过其他机制发送了这个漏洞,我们的签名可能会失效。因此,攻击者和防御者之间的永恒斗争依然在继续。
注意
基于恶意流量样本创建流量签名是防御网络未知威胁的关键步骤。分析像这里描述的捕获文件是学习如何编写这些签名的好方法。要了解更多关于入侵检测和攻击签名的信息,请访问 Snort 项目: www.snort.org/.
远程访问木马
ratinfected.pcapng
到目前为止,我们已经在一定了解攻击背景的情况下分析了安全事件。这是学习攻击样式的好方法,但它并不完全贴近现实。在大多数实际的网络防御场景中,负责防守网络的人不会检查网络上每一个传输的数据包。相反,他们会使用某种形式的 IDS 来提醒他们网络流量中的异常情况,依据的是预定义的攻击签名。
在下一个示例中,我们将从一个简单的警报开始,假设我们是现实世界中的分析师。在这种情况下,我们的 IDS 触发了以下警报:
[**] [1:132456789:2] CyberEYE RAT Session Establishment [**]
[Classification: A Network Trojan was detected] [Priority: 1]
07/18-12:45:04.656854 172.16.0.111:4433 -> 172.16.0.114:6641
TCP TTL:128 TOS:0x0 ID:6526 IpLen:20 DgmLen:54 DF
***AP*** Seq: 0x53BAEB5E Ack: 0x18874922 Win: 0xFAF0 TcpLen: 20
我们的下一步是查看触发此警报的签名规则:
alert tcp any any -> $HOME_NET any (msg:"CyberEYE RAT Session Establishment";
content:"|41 4E 41 42 49 4C 47 49 7C|"; classtype:trojan-activity;
sid:132456789; rev:2;)
该规则设置为当它检测到任何来自外部网络进入内部网络的数据包,其中包含十六进制内容41 4E 41 42 49 4C 47 49 7C时触发警报,这些内容转换为人类可读的 ASCII 字符ANA BILGI。当检测到时,警报触发,表示可能存在 CyberEYE 远程访问木马(RAT)。RAT 是一种在目标计算机上悄悄运行的恶意程序,为攻击者提供远程访问目标计算机的手段。
注意
CyberEYE 是曾经流行的土耳其工具,用于创建 RAT 可执行文件并管理被攻陷的主机。具有讽刺意味的是,Snort 规则在这里触发的是字符串 ANA BILGI,这个词在土耳其语中表示“基本信息”。
现在我们来看一下与ratinfected.pcapng中的警报相关的流量。这个 Snort 警报通常只会捕获触发警报的单个数据包,但幸运的是,我们拥有两台主机之间的整个通信序列。为了跳到重点,按照以下方式搜索 Snort 规则中提到的十六进制字符串:
-
选择Edit ▶ Find Packet,或按 CTRL-F。
-
从下拉菜单中选择Hex Value选项。
-
在文本区域中输入值 41 4E 41 42 49 4C 47 49 7C。
-
点击Find。
如图 12-23 所示,你现在应该能看到数据部分中包 4 ➊中首次出现的十六进制字符串。

图 12-23:在数据包 4 中首次看到 Snort 警报中的内容字符串。
如果你选择多次点击Find,你会发现这个字符串也出现在包 5、10、32、156、280、405、531 和 652 中。尽管这个捕获文件中的所有通信都是在攻击者(172.16.0.111)和目标(172.16.0.114)之间进行的,但似乎有些字符串实例出现在不同的对话中。虽然包 4 和包 5 使用端口 4433 和 6641 进行通信,但其他大多数实例发生在端口 4433 和其他随机选择的临时端口之间。我们可以通过查看对话窗口的 TCP 选项卡来确认存在多个对话,如图 12-24 所示。
我们可以通过为不同的对话着色来在这个捕获文件中直观地区分它们,如下所示:
-
在包列表窗格上方的过滤器对话框中,输入过滤器(tcp.flags.syn == 1) && (tcp.flags.ack == 0)。然后按 ENTER。这将选中流量中每个对话的初始 SYN 包。
-
右键点击第一个包并选择Colorize Conversation。
-
选择TCP,然后选择一个颜色。
-
对剩余的 SYN 包重复此过程,为每个包选择不同的颜色。
-
完成后,点击X以移除过滤器。

图 12-24:攻击者和目标之间存在三个独立的对话。
为对话着色后,我们可以清除过滤器,查看它们之间的关系,帮助我们跟踪两台主机之间的通信过程。第一个对话(端口 6641/4433)是两台主机开始通信的地方,因此是一个很好的起点。右键点击对话中的任何数据包,选择Follow TCP Stream查看传输的数据,如图 12-25 所示。

图 12-25:第一个对话产生了有趣的结果。
随即,我们看到攻击者向目标发送了文本字符串 ANABILGI|556 ➊。因此,目标响应了一些基本的系统信息,包括计算机名称(CSANDERS-6F7F77)和正在使用的操作系统(Windows XP Service Pack 3) ➋,并开始反复将字符串 BAGLIMI? 发送回攻击者 ➌。攻击者唯一的回馈是字符串 CAPSCREEN60 ➍,该字符串出现了六次。
攻击者返回的这个CAPSCREEN60字符串很有趣,接下来我们看看它指向哪里。为此,请确保你已经清除了任何显示过滤器,并使用搜索对话框在数据包中搜索文本字符串CAPSCREEN60,选择 字符串 选项并确保已选择 数据包字节 选项来执行搜索。
执行此搜索后,我们在第 27 个数据包中找到了第一个 CAPSCREEN60 字符串。这个信息的有趣之处在于,当字符串从攻击者发送到客户端时,客户端确认接收到数据包,并在第 29 个数据包中启动了一个新会话。你应该能更容易地注意到新会话的开始,因为之前应用的着色规则会帮助你辨认。
现在,如果我们跟踪这个新会话的 TCP 流输出(如图 12-26 所示),我们看到熟悉的字符串ANABILGI|12,接着是SH|556,最后是CAPSCREEN|C:\WINDOWS\jpgevhook.dat|84972 ➊。注意 CAPSCREEN 字符串后面指定的文件路径,后面跟着一些无法读取的文本。最引人注目的是,这段无法读取的文本前面有一个字符串 JFIF ➋,快速 Google 搜索会告诉你,它通常出现在 JPG 文件的开头。

图 12-26:攻击者似乎正在发起请求以获取 JPG 文件。
到此为止,我们可以安全地得出结论,攻击者发起了请求以传输这张 JPG 图片。但更重要的是,我们开始看到流量中出现了命令结构。似乎 CAPSCREEN 是攻击者用来启动 JPG 文件传输的命令。事实上,每当发送 CAPSCREEN 命令时,结果都是相同的。为了验证这一点,可以查看每个包含 CAPSCREEN 命令的会话的 TCP 流,或者尝试使用 Wireshark 的 IO 图形功能,如下所示:
-
选择 统计信息 ▶ IO 图形。
-
点击加号(+)按钮以添加五行。
-
分别将过滤器 tcp.stream eq 2、tcp.stream eq 3、tcp.stream eq 4、tcp.stream eq 5 和 tcp.stream eq 6 插入到显示过滤器中,并为每个过滤器命名。
-
将每个条目的 y 轴刻度更改为 字节/秒。
-
点击 图表 1、图表 2、图表 3、图表 4 和 图表 5 按钮以启用为指定过滤器显示的数据点。
图 12-27 显示了结果图。

图 12-27:此图表显示了类似的活动似乎在重复出现。
根据这张图表,看起来每个会话大致包含相同数量的数据,并且持续时间相同。我们现在可以得出结论,这一活动多次重复。
你可能已经对传输中的 JPG 图像的内容有一些想法,那么让我们看看能否查看其中一个文件。要从 Wireshark 提取 JPG 数据,执行以下步骤:
-
首先,像我们在图 12-25 中做的那样,跟踪适当数据包的 TCP 流。数据包 29 是一个不错的选择。
-
必须将通信隔离,以便我们只看到从目标发送到攻击者的数据流。通过选择下拉菜单旁边的箭头(标记为“整个会话 (85033 字节)”)来执行此操作。确保选择正确的方向流量,即 172.16.0.114:6643 --> 172.16.0.111:4433(85 KB)。
-
在显示数据为下拉菜单中,选择RAW。
-
点击另存为按钮保存数据,确保以.jpg文件扩展名保存文件。
如果现在尝试打开图像,你可能会惊讶地发现它无法打开。这是因为我们还需要执行最后一步。与在第十章中从 FTP 流量中干净提取文件的情况不同,这里的流量向数据中添加了一些额外的内容。在这种情况下,TCP 流中的前两行实际上是恶意软件的命令序列的一部分,而不是构成 JPG 的实际数据(参见图 12-28)。当我们保存流时,这些多余的数据也被保存了。因此,文件查看器在寻找 JPG 文件头时看到的内容与它期望的内容不匹配,因此无法打开图像。

图 12-28:恶意软件添加的多余数据阻止文件正确打开。
解决此问题是一个简单的过程,只需使用十六进制编辑器稍微操作一下。这一过程称为文件雕刻。要从导出的数据中雕刻出这个文件,请完成以下过程:
-
在查看图 12-28 中的 TCP 流时,点击另存为按钮。选择一个容易记住的文件名,并将文件保存到一个你稍后可以再次访问的位置。
-
从
www.x-ways.net/winhex/下载并安装 WinHex。 -
执行 WinHex 并打开刚刚从 Wireshark 保存的文件。
-
使用鼠标选择文件开头的所有多余数据。这应该包括所有在
FF D8 FF E0字节之前的内容,这些字节表示新 JPG 文件的开始。要选择的字节在图 12-29 中已突出显示。![image]()
图 12-29:从 JPG 文件中移除多余的字节
-
按下删除键以删除选定的数据。
-
点击 WinHex 主工具栏中的保存按钮以保存您的更改。
注意
我喜欢在 Windows 上使用 WinHex 来执行这项任务,但任何您熟悉的十六进制编辑器都可以。
去除不需要的数据字节后,您现在应该能够打开文件。应该清楚地看到木马正在捕获目标桌面的屏幕截图并将其传回攻击者(图 12-30)。在这些通信序列完成后,通信通过正常的 TCP 断开序列结束。
这个场景是入侵分析员在分析基于 IDS 警报的流量时所遵循的思维过程的典型例子:
• 检查警报以及生成它的签名。
• 确认签名匹配是否在正确的上下文中出现。
• 检查流量以了解攻击者在受感染机器上做了什么。
• 在更多敏感信息从受感染目标泄露之前,开始对问题进行遏制。

图 12-30:传输的 JPG 是目标计算机的屏幕截图。
漏洞利用工具包和勒索软件
cryptowall4_c2.pcapng,ek_to_cryptowall4.pcapng
在我们的最后一个场景中,我们将查看另一个始于 IDS 警报的调查。我们将探索从感染系统生成的实时数据包,然后尝试追踪入侵的源头。这个例子将利用真实的恶意软件,您可能会在您的网络中发现它感染了设备。
故事始于 Sguil 控制台中由 Snort 生成的 IDS 警报,如图 12-31 所示。Sguil 是一个用于管理、查看和调查来自一个或多个传感器的 IDS 警报的工具。它的用户界面并不最为吸引人,但它已经存在一段时间,并且是安全分析员非常流行的工具。
在 Sguil 中有大量关于此警报的信息可供查看。上方窗口 ➊ 显示了警报的摘要。在这里,您可以看到警报生成的时间、源和目标 IP 地址及端口、协议以及匹配的 IDS 签名生成的事件信息。在此案例中,192.168.122.145 是本地友好系统,它通过端口 80 与外部未知系统 184.170.149.44 进行通信,而端口 80 通常与 HTTP 流量相关。由于该系统在与指示恶意通信的签名相关时出现,因此假设外部系统是恶意的,并且对它知之甚少。匹配此流量的签名代表了 CryptoWall 恶意软件家族的注册流量,表明该恶意软件的某个变种已经安装在友好系统上。

图 12-31:此 IDS 警报表明存在 CryptoWall 4 感染。
Sguil 控制台提供了匹配规则的语法 ➋ 和匹配该规则的单个数据包数据 ➌。请注意,数据包信息被分解为协议头和数据部分,类似于 Wireshark 中展示数据包信息的方式。不幸的是,Sguil 只提供匹配的单个数据包信息,我们需要深入挖掘。下一步是使用 Wireshark 检查与此警报相关的流量,尝试验证流量并查看发生了什么。该流量包含在文件cryptowall4_c2.pcapng中。
这个数据包捕获包含了在警报发生时进行的通信,并且并不复杂。第一次通信发生在数据包 1 至 16 之间,我们可以通过跟踪该通信的 TCP 流轻松查看它(图 12-32)。在捕获开始时,本地系统打开一个 TCP 连接到敌对主机的 80 端口,并向 URL homealldaylong.com/76N1Lm.php?x4tk7t4jo6 ➊ 发出一个POST请求,内容包含少量的字母数字数据 ➋。敌对主机以一个字母数字字符串 ➍ 和一个HTTP 200 OK响应代码 ➌ 回应,随后连接被正常终止。

图 12-32:这些主机之间通过 HTTP 传输少量数据。
如果你查看捕获文件的其余部分,你会看到在这些主机之间相同的序列重复出现,每次传输的数据量不同。使用过滤器http.request.method == "POST"可以查看三个具有相似 URL 结构的不同连接(图 12-33)。

图 12-33:URL 结构显示不同的数据传递到相同的页面。
76N1Lm.php部分(网页)保持不变,但其余内容(传递给页面的参数和数据)则有所不同。重复的通信序列以及请求的结构与恶意软件的命令与控制(C2)行为一致,并且与生成警报的特征匹配。因此,本地系统很可能感染了 CryptoWall,就像特征所暗示的那样。你可以通过检查流行的 CryptoWall Tracker 研究页面上的类似样本进一步验证这一点:* www.cryptowalltracker.org/cryptowall-4.html#networktraffic。
注意
解密友好系统与敌对系统在 C2 序列中通信的数据对于本书来说可能有些复杂。但如果你感兴趣,可以在这里阅读更多相关内容: www.cryptowalltracker.org/communication-protocol.html。
现在你已经确认了基于恶意软件的 C2 通信正在发生,接下来最好处理这个问题并修复受感染的机器。特别是当涉及到像 CryptoLocker 这样的恶意软件时,这一点尤为重要,因为它试图加密用户的数据,并且只有在用户支付了高额赎金后才会提供解密密钥——因此,类似的恶意软件被称为勒索软件。修复问题的步骤超出了本书的范围,但在实际的场景中,这些将是安全分析师接下来的行动。
一个常见的后续问题是,友好的机器是如何最初感染的。如果能够确定这一点,你可能会发现其他设备也以类似的方式感染了其他恶意软件,或者你可能能够开发保护或检测机制以防止未来的感染。
警报数据包仅在感染后显示了活跃的 C2 序列。在执行安全监控和持续数据包捕获的网络中,许多网络传感器被配置为存储数据包数据几个小时或几天,以便进行取证调查。毕竟,并不是每个组织都能够在警报发生的瞬间做出响应。临时存储数据包使我们能够查看友好主机在启动之前看到的 C2 序列的数据包。这些数据包包含在文件ek_to_cryptowall4.pcapng中。
浏览该数据包捕获文件的初步查看告诉我们,还有很多包需要查看,但它们都是 HTTP 请求。既然我们已经知道 HTTP 的工作原理,那么让我们直奔主题,使用显示过滤器http.request仅显示请求数据包。这将显示来自友好主机的 11 个 HTTP 请求(图 12-34)。

图 12-34:来自友好主机的 11 个 HTTP 请求
第一个请求来自友好的主机 192.168.122.145,目标是一个未知的外部主机 113.20.11.49。通过检查该数据包的 HTTP 部分(图 12-35),我们得知用户请求了页面www.sydneygroup.com.au/index.php/services/ ➊,并且是从 Bing 搜索* sydneygroup.com.au * ➋跳转过来的。到目前为止,这看起来是正常的。
接下来,友好的主机向另一个未知的外部主机 45.32.238.202 发出了四个请求,分别位于数据包 35、39、123 和 130 中。正如你在之前的示例中看到的,浏览器在查看存储了嵌入内容或广告的网页时,通常会从其他主机检索内容。这本身并不令人担忧,尽管这些请求中的域名看起来有些随机且可疑。

图 12-35:一个 HTTP 请求到未知的外部主机
在数据包 39 的 GET 请求中,事情变得有趣了。跟踪此交换的 TCP 流(图 12-36),你会注意到请求了一个名为 bXJkeHFlYXhmaA 的文件 ➊。这个文件的名称有些奇怪,并且没有包含文件扩展名。

图 12-36:下载了一个名字奇怪的 Flash 文件。
经过仔细检查,我们看到 web 服务器将该文件的内容识别为 x-shockwave-flash ➋。Flash 是一种在浏览器中用于流媒体播放的流行插件。看到设备下载 Flash 内容并不异常,但值得注意的是,Flash 以其软件漏洞而臭名昭著,且这些漏洞经常得不到修复。Flash 文件在请求后成功下载。
在 Flash 文件下载后,数据包 130 中又有一个请求,要求下载一个类似命名的文件。跟踪这个 TCP 流(图 12-37),你会看到请求了一个名为 enVjZ2dtcnpz 的文件 ➊。此处没有通过扩展名或服务器识别文件类型。请求后,客户端下载了一个 358,400 字节的无法读取的数据块 ➋。

图 12-37:又下载了一个名字奇怪的文件,但未识别出文件类型。
在下载该文件不到 20 秒后,你应该在 图 12-34 中看到一些熟悉的内容。从数据包 441 开始,友好的主机开始向两个不同的服务器发送 HTTP POST 请求,使用之前观察到的相同 C2 模式。我们很可能已经找到了感染的源头。下载的两个文件是罪魁祸首。第一个文件来自数据包 39 的请求,交付了 Flash 漏洞,第二个文件来自数据包 130 的请求,交付了恶意软件。
注意
你可以使用恶意软件分析技术来解码和分析数据包捕获中的文件。如果你对逆向工程恶意软件感兴趣,我推荐 Michael Sikorski 和 Andrew Honig 的《实用恶意软件分析》(2012 年),这是一本来自 No Starch Press 的书,也是我个人的最爱。
这个场景代表了最常见的感染技巧之一。用户正在浏览互联网时,偶然进入了一个被恶意重定向代码感染的网站,这些代码来自一个利用工具包。这些工具包感染合法服务器,旨在识别客户端以确定其漏洞。被感染的页面被称为 工具包的着陆页,其目的是将客户端重定向到另一个包含该工具包已确定有效的漏洞的站点。
你刚刚看到的这些数据包来自于 Angler 利用工具包,它可能是 2015 年和 2016 年最常见的工具包。当用户访问一个被 Angler 感染的网站时,该工具包会判断用户会受到特定 Flash 漏洞的攻击。Flash 文件被传送,系统被利用,CryptoWall 恶意软件的二次负载被下载并安装到主机上。整个过程如图 12-38 所示。

图 12-38:利用工具包感染序列
最终思考
关于在与安全相关的场景中分析数据包捕获、分析常见攻击以及响应 IDS 警报,完全可以写成整本书。在本章中,我们考察了一些常见的扫描和枚举技术、一种常见的 MITM 攻击,以及一些关于系统如何被利用以及可能会发生什么的例子。
第十三章:无线数据包分析

无线网络的世界与传统的有线网络有所不同。尽管我们仍然在处理像 TCP 和 IP 这样的常见通信协议,但在进入 OSI 模型的最低层时,情况有些变化。在这里,数据链路层由于无线网络和物理层的特性而显得尤为重要。与变化不大的以太网等简单有线协议不同,我们需要考虑像 802.11 这样的无线协议的细微差别,而这些协议发展得相当迅速。这给我们访问的数据以及如何捕获这些数据带来了新的限制。
考虑到这些额外的因素,本书专门有一章讲述如何在无线网络上进行数据包捕获和分析,这一点应该不足为奇。在本章中,我们将讨论为什么无线网络在数据包分析中是独特的,并且如何克服任何挑战。当然,我们将通过实际的无线网络捕获案例来进行分析。
物理考虑
捕获和分析通过无线网络传输的数据时,首先要考虑的是物理传输介质。直到现在,我们还没有考虑物理层,因为我们一直通过物理电缆进行通信。现在,我们通过看不见的无线电波进行通信,数据包就在我们身边飞过。
一次嗅探一个频道
捕获无线局域网(WLAN)流量时一个特别需要考虑的因素是无线频谱是一个共享介质。与有线网络不同,在有线网络中,每个客户端都有自己的网络电缆连接到交换机,而无线通信介质是客户端共享的空气空间,其大小有限。一个 WLAN 只会占用 802.11 频谱的一部分,这允许多个系统在同一个物理区域内操作,并使用频谱的不同部分。
注意
无线网络基于由电气和电子工程师协会(IEEE)开发的 802.11 标准。本章中,术语 无线网络 和 WLAN 指的是遵循 802.11 标准的网络。这个标准的最流行版本包括 802.11a、b、g 和 n。每个版本都有一套独特的功能和特性,像 n 这样的较新标准提供了更快的速度。它们都仍然使用相同的频谱。
空间的分隔通过将频谱划分为操作频道来实现。频道只是 802.11 无线频谱的一部分。在美国,提供 11 个频道(在一些其他国家允许更多)。这很重要,因为,就像 WLAN 只能在一个频道上操作一样,我们也只能在一个频道上嗅探数据包,正如图 13-1 所示。因此,如果你正在故障排除一个在频道 6 上运行的 WLAN,你必须配置系统以捕获频道 6 上的流量。

图 13-1:无线嗅探可能是繁琐的,因为它一次只能在一个频道上进行。
传统的无线嗅探一次只能在一个频道上进行,但有一个例外:某些无线扫描应用使用一种叫做频道跳跃的技术,快速切换频道以收集数据。这个类型中最流行的工具之一,Kismet(www.kismetwireless.net/),每秒最多可以跳跃 10 个频道,这使得它非常有效地同时嗅探多个频道。
无线信号干扰
在无线通信中,我们有时不能依赖于通过空气传输的数据的完整性。可能会有一些干扰信号的因素。无线网络包括一些处理干扰的功能,但这些功能并不总是有效。因此,在无线网络中捕获数据包时,你必须密切关注周围环境,确保没有显著的干扰源,比如大的反射面、大型刚性物体、微波炉、2.4 GHz 的电话、厚墙或高密度的表面。这些都会导致数据包丢失、数据包重复和数据包格式错误。
通道之间的干扰也是一个值得关注的问题。虽然你一次只能嗅探一个通道,但这有一个小的 caveat:无线网络频谱中有多个传输通道可用,但由于空间有限,通道之间存在轻微的重叠,正如图 13-2 所示。这意味着,如果频道 4 和频道 5 上有流量,而你正在嗅探其中一个频道,你很可能会捕获到另一个频道的数据包。通常,在同一地区共存的网络会设计为使用不重叠的频道 1、6 和 11,所以你可能不会遇到这个问题。但为了以防万一,你应该理解其发生的原因。

图 13-2:由于频谱空间有限,通道之间存在重叠。
检测和分析信号干扰
排查无线信号干扰并不是通过查看 Wireshark 中的数据包就能完成的。如果你打算经常或以此为职业来排查 WLAN 故障,你肯定需要定期检查信号干扰。这个任务是通过频谱分析仪来完成的,它能显示整个频谱的数据或干扰。
商业级频谱分析仪的价格可能高达数千美元,但有一个适合日常使用的优秀解决方案。MetaGeek 生产了一款 USB 硬件设备 Wi-Spy,可以监控整个 802.11 频谱中的信号。当与 MetaGeek 的 inSSIDer 或 Chanalyzer 软件配合使用时,该硬件能够图形化显示频谱,以便帮助排除故障。Chanalyzer 的示例输出显示在图 13-3 中。

图 13-3:此 Chanalyzer 输出显示了在 Wi-Fi 频谱上均匀分布的四个信号。
无线网卡模式
在开始嗅探无线数据包之前,我们需要了解无线网卡在数据包捕获方面可以操作的不同模式。
有四种无线网卡模式可供选择:
受管模式 当你的无线客户端直接连接到无线接入点(WAP)时,使用此模式。在这种情况下,与无线网卡相关联的驱动程序依赖 WAP 来管理整个通信过程。
临时模式 当你有一个无线网络设置,设备直接相互连接时,就使用此模式。在这种模式下,两个想要通信的无线客户端共同承担无线接入点(WAP)通常负责的任务。
主模式 一些高端无线网卡还支持主模式。该模式允许无线网卡与专用驱动程序配合工作,使计算机能够充当其他设备的无线接入点(WAP)。
监控模式 这是我们工作中最重要的模式。当你希望无线客户端停止发送和接收数据,而仅仅监听空中飞行的数据包时,就需要使用监控模式。为了让 Wireshark 能够捕获无线数据包,你的无线网卡及其驱动程序必须支持监控模式(也称为 RFMON 模式)。
大多数用户仅在受管模式或临时模式下使用无线网卡。每种模式的操作方式通过图 13-4 进行了图形化展示。

图 13-4:不同无线网卡模式
注意
我经常被问到推荐哪种无线网卡用于无线数据包分析。我使用并强烈推荐 ALFA 网络的产品。它们的产品被认为是市场上最好的之一,能够确保你捕获到每一个可能的数据包,而且价格实惠、便于携带。ALFA 的产品可以通过大多数在线计算机硬件零售商购买。
在 Windows 中进行无线嗅探
即使你拥有支持监视模式的无线网卡,大多数基于 Windows 的无线网卡驱动程序也不允许你切换到该模式。这意味着你只能捕获从你用来连接网络的设备的无线接口传输的包。要捕获在一个频道上所有设备之间的包,你需要额外的硬件。
配置 AirPcap
Riverbed Technologies 的 AirPcap(www.riverbed.com/)旨在克服 Windows 对无线数据包分析的限制。AirPcap 是一款小型 USB 设备,类似于闪存驱动器,如图 13-5 所示。它设计用于从一个或多个指定频道捕获无线流量。AirPcap 使用 WinPcap 驱动程序和一个特殊的客户端配置工具。

图 13-5:AirPcap 设备非常紧凑,便于与笔记本电脑一起携带。
AirPcap 配置程序(如图 13-6 所示)使用起来非常简单,只有几个可配置选项:
接口 你可以在这里选择用于捕获的设备。一些高级分析场景可能要求你使用多个 AirPcap 设备,分别在多个频道上同时嗅探。
闪烁 LED 点击此按钮将使 AirPcap 设备上的 LED 灯闪烁。主要用于识别你正在使用的特定适配器,特别是当你有多个 AirPcap 设备时。
频道 在此字段中,选择你希望 AirPcap 监听的频道。

图 13-6:AirPcap 配置程序
扩展频道 在此,你可以选择一个扩展频道,这是 802.11n 适配器的一个功能,允许创建更宽的频道。
在帧中包含 802.11 FCS 默认情况下,一些系统会从无线数据包中去除最后四位校验和。这种校验和,称为帧检验序列(FCS),用于确保数据包在传输过程中没有被损坏。除非你有特殊理由,否则勾选此框以包含 FCS 校验和。
捕获类型 此处有三个选项:802.11 仅、802.11 + 无线电和 802.11 + PPI。802.11 仅选项包含所有捕获数据包的标准 802.11 数据包头。802.11 + 无线电选项包括此数据包头,并在其前面添加一个 radiotap 头,包含有关数据包的附加信息,例如数据速率、频率、信号强度和噪声水平。802.11 + PPI 选项则添加了每包信息头,包含有关 802.11n 数据包的附加信息。
FCS 过滤器 即使你取消勾选“在帧中包含 802.11 FCS”框,此选项仍然允许你过滤掉被 FCS 判断为损坏的数据包。使用“有效帧”选项只显示 FCS 认为能够成功接收的数据包。
WEP 配置 这个区域(可以在 AirPcap 控制面板的“Keys”标签页中访问)允许你输入 WEP 解密密钥,用于你将要嗅探的网络。为了能够解读由 WEP 加密的数据,你需要在此字段中输入正确的 WEP 密钥。WEP 密钥在《成功的 WEP 认证》一节中有详细讨论,详见第 309 页。
使用 AirPcap 捕获流量
一旦你安装并配置了 AirPcap,捕获过程应该对你来说很熟悉。只需启动 Wireshark 并选择 AirPcap 接口开始从中收集数据包(参见图 13-7)。

图 13-7:选择 AirPcap 接口来捕获数据包
请记住,你将从在 AirPcap 配置工具中选择的频道捕获数据包。如果你没有看到你想要的数据包,可能是因为你选择了错误的频道。你可以通过停止当前的捕获,选择 AirPcap 配置工具中的新频道,然后重新启动捕获来更改频道。在更改频道时,你不能同时进行数据包捕获。
如果你需要验证在 Wireshark 中捕获的频道,可以通过查看无线捕获统计信息来轻松确认。方法是从主下拉菜单中点击Wireless ▶ WLAN Traffic。弹出的窗口将显示观察到的设备及其信息,包括 802.11 频道,如图 13-8 所示。

图 13-8:无线 LAN 统计窗口显示数据是通过监听 11 频道捕获的。
在 Linux 中无线嗅探
在 Linux 中嗅探仅仅是启用无线网卡的监控模式并启动 Wireshark 的问题。不幸的是,启用监控模式的过程因每个无线网卡型号的不同而有所不同,因此我无法提供具体的操作建议。事实上,一些无线网卡根本不需要启用监控模式。最好的办法是通过快速的 Google 搜索查找你的网卡型号,确认是否需要启用监控模式,如果需要的话,查找具体的操作方法。
在 Linux 中启用监控模式的常见方法之一是通过其内建的无线扩展。你可以使用iwconfig命令访问这些无线扩展。如果你在终端中输入iwconfig,应该能看到类似这样的结果:
$ iwconfig
➊ Eth0 no wireless extensions
Lo0 no wireless extensions
➋ Eth1 IEEE 802.11g ESSID: "Tesla Wireless Network"
Mode: Managed Frequency: 2.462 GHz Access Point: 00:02:2D:8B:70:2E
Bit Rate: 54 Mb/s Tx-Power-20 dBm Sensitivity=8/0
Retry Limit: 7 RTS thr: off Fragment thr: off
Power Management: off
Link Quality=75/100 Signal level=-71 dBm Noise level=-86 dBm
Rx invalid nwid: 0 Rx invalid crypt: 0 Rx invalid frag: 0
Tx excessive retries: 0 Invalid misc: 0 Missed beacon: 2
iwconfig命令的输出显示,Eth1接口可以进行无线配置。这一点很明显,因为它显示了 802.11g 协议的数据➋,而Eth0和Lo0接口则返回了no wireless extensions的提示➊。
除了此命令提供的所有无线信息,如无线扩展服务集 ID(ESSID)和频率外,请注意Eth1下的第二行显示当前模式已设置为管理模式。这是我们想要更改的设置。
要将Eth1接口更改为监控模式,你必须以 root 用户身份登录,无论是直接登录还是通过切换用户(su)命令,如下所示:
$ su
Password: <enter root password here>
一旦你是 root 用户,你可以输入命令来配置无线接口选项。要将Eth1配置为监控模式,请输入以下命令:
# iwconfig eth1 mode monitor
一旦 NIC 进入监控模式,再次运行iwconfig命令应该能反映出你的更改。现在,通过输入以下命令来确保Eth1接口正常工作:
# iwconfig eth1 up
我们还将使用iwconfig命令来更改我们监听的频道。通过输入以下命令将Eth1接口的频道更改为频道 3:
# iwconfig eth1 channel 3
注意
你可以在捕获数据包时实时更改频道,所以不要犹豫,随时更改。iwconfig命令也可以编写成脚本,以简化这个过程。
完成这些配置后,启动 Wireshark 并开始数据包捕获。
802.11 数据包结构
80211beacon.pcapng
无线数据包与有线数据包的主要区别在于增加了 802.11 头部。这个第二层头部包含有关数据包以及其传输媒介的额外信息。802.11 数据包有三种类型:
管理 这些数据包用于在第二层建立主机之间的连接。一些重要的管理数据包子类型包括认证、关联和 beacon 数据包。
控制 控制数据包允许管理和数据数据包的传输,并且与拥塞管理相关。常见的子类型包括请求发送(request-to-send)和清除发送(clear-to-send)数据包。
数据 这些数据包包含实际数据,并且是唯一可以从无线网络转发到有线网络的数据包类型。
无线数据包的类型和子类型决定了其结构,因此可能存在大量不同的结构。我们将通过查看文件80211beacon.pcapng中的一个数据包来研究其中一种结构。该文件包含一个称为beacon的管理数据包示例,如图 13-9 所示。
beacon 是你能找到的最具信息性的无线数据包之一。它作为广播数据包从 WAP 通过无线信道发送,通知任何正在监听的无线客户端该 WAP 可用,并定义必须设置的参数以便连接到它。在我们的示例文件中,可以看到该数据包在 802.11 头部的类型/子类型字段中被定义为 beacon ➊。
802.11 管理帧头中还包含大量附加信息,包括以下内容:
时间戳 数据包传输的时间
Beacon 间隔 beacon 数据包重新传输的间隔时间
能力信息 有关 WAP 硬件能力的信息

图 13-9:这是一个 802.11 beacon 数据包。
SSID 参数设置 WAP 广播的 SSID(网络名称)
支持的速率 WAP 支持的数据传输速率
DS 参数集 WAP 广播的频道
标头还包括源和目的地址以及厂商特定信息。
基于此,我们可以确定一些关于示例文件中广播信标的 WAP 的事情。显然,它是一个使用 802.11b 标准(B)的 D-Link 设备➋,运行在 11 频道➍。
尽管 802.11 管理包的确切内容和目的会有所变化,但其基本结构仍与此示例相似。
向数据包列表窗格添加无线特定列
在前面的章节中,我们已经利用 Wireshark 灵活的界面添加了适应情况的列。在继续进行其他无线分析之前,添加以下三个列到数据包列表窗格会很有帮助。
• 频道列,显示捕获数据包时所在的频道
• 信号强度列,显示捕获数据包的信号强度(单位:dBm)
• 数据速率列,显示捕获数据包的吞吐速率
这些指示器在排查无线连接问题时非常有帮助。例如,即使你的无线客户端软件显示信号强度非常好,进行捕获并检查这些列可能会显示一个与此声明不符的数字。
要将这些列添加到数据包列表窗格,请按照以下步骤操作:
-
选择编辑 ▶ 首选项。
-
导航到列部分并点击+。
-
在标题字段中输入Channel,在类型下拉菜单中选择Custom,并在字段名称框中使用过滤器wlan_radio.channel。
-
对信号强度和数据速率列重复此过程,分别为它们命名,并在字段名称下拉列表中选择wlan_radio.signal_dbm和wlan_radio.data_rate。图 13-10 显示了在添加了所有三个列后,首选项窗口的样子。
![image]()
图 13-10:在数据包列表窗格中添加 IEEE 无线特定列
-
点击确定保存更改。
无线特定过滤器
我们在第四章中讨论了捕获和显示过滤器的好处。在有线基础设施中,过滤流量要容易得多,因为每个设备都有自己的专用电缆。然而,在无线网络中,无线客户端生成的所有流量都在共享频道上共存,这意味着对任何一个频道的捕获可能包含来自几十个客户端的流量。本节将介绍一些可以帮助你找到特定流量的包过滤器。
为特定 BSS ID 过滤流量
网络中的每个 WAP 都有一个唯一的标识名称,称为基本服务集标识符(BSS ID)。这个名称会在接入点传输的每个无线管理包和数据包中发送。
一旦你知道了想要检查的 BSS ID 名称,实际上你只需要找到从那个特定 WAP 发送的一个数据包。Wireshark 会在数据包列表窗格的“信息”列中显示发送的 WAP,所以找到这一信息通常很容易。
一旦从感兴趣的 WAP 获取到一个数据包,找到其 802.11 头部中的 BSS ID 字段。这是你用来设置过滤器的地址。在找到 BSS ID MAC 地址后,你可以使用以下过滤器:
wlan.bssid == 00:11:22:33:44:55
然后你将看到仅通过指定 WAP 流动的流量。
过滤特定无线数据包类型
在本章前面,我们讨论了你可能在网络上看到的不同类型的无线数据包。你经常需要根据这些类型和子类型进行过滤。这可以通过过滤器 wlan.fc.type 来针对特定类型进行过滤,或者通过 wlan.fc.type_subtype 来针对特定类型或子类型组合进行过滤。例如,若要过滤 NULL 数据包(一个十六进制值为 Type 2 Subtype 4 的数据包),可以使用过滤器 wlan.fc.type_subtype == 0x24。表 13-1 提供了一个常用过滤器的快速参考,帮助你过滤 802.11 数据包类型和子类型。
表 13-1: 无线类型/子类型及其相关过滤器语法
| 帧类型/子类型 | 过滤器语法 |
|---|---|
| 管理帧 | wlan.fc.type == 0 |
| 控制帧 | wlan.fc.type == 1 |
| 数据帧 | wlan.fc.type == 2 |
| 关联请求 | wlan.fc.type_subtype == 0x00 |
| 关联响应 | wlan.fc.type_subtype == 0x01 |
| 重新关联请求 | wlan.fc.type_subtype == 0x02 |
| 重新关联响应 | wlan.fc.type_subtype == 0x03 |
| 探测请求 | wlan.fc.type_subtype == 0x04 |
| 探测响应 | wlan.fc.type_subtype == 0x05 |
| 信标 | wlan.fc.type_subtype == 0x08 |
| 取消关联 | wlan.fc.type_subtype == 0x0A |
| 认证 | wlan.fc.type_subtype == 0x0B |
| 解除认证 | wlan.fc.type_subtype == 0x0C |
| 动作帧 | wlan.fc.type_subtype == 0x0D |
| 块确认请求 | wlan.fc.type_subtype == 0x18 |
| 块确认 | wlan.fc.type_subtype == 0x19 |
| 节能轮询 | wlan.fc.type_subtype == 0x1A |
| 请求发送 | wlan.fc.type_subtype == 0x1B |
| 清除发送 | wlan.fc.type_subtype == 0x1C |
| 确认 | wlan.fc.type_subtype == 0x1D |
| 无争用期结束 | wlan.fc.type_subtype == 0x1E |
| NULL 数据 | wlan.fc.type_subtype == 0x24 |
| QoS 数据 | wlan.fc.type_subtype == 0x28 |
| NULL QoS 数据 | wlan.fc.type_subtype == 0x2C |
过滤特定频率
如果你正在检查包含来自多个频道的数据包的流量,基于每个单独的频道进行过滤会非常有用。例如,如果你预期只在频道 1 和 6 上有流量,你可以输入一个过滤器来显示所有频道 11 的流量。如果你发现有流量,那么你就知道可能出现了问题——可能是配置错误或恶意设备。要针对特定频道进行过滤,可以使用以下过滤器语法:
wlan_radio.channel == 11
这将显示频道 11 上的所有流量。你可以将11值替换为你希望过滤的频道。你可以使用数百个其他有用的过滤器来过滤无线网络流量。你可以在 Wireshark wiki 上查看更多的无线捕获过滤器,网址为 wiki.wireshark.org/。
保存无线配置文件
配置特定的列并保存自定义过滤器以进行无线数据包分析确实需要一些工作。与其每次都重新配置和移除列与过滤器,你可以创建并保存一个自定义配置文件,快速在有线和无线分析配置之间切换。
要保存一个自定义配置文件,首先配置无线列和过滤器,使其符合你的喜好。然后,右键单击屏幕右下角的活动配置文件列表,点击新建。命名配置文件为无线,然后点击确定。
无线安全
部署和管理无线网络时,最大的关注点是通过无线网络传输的数据的安全性。由于数据在空中飞行,任何知道如何的人都可以轻松截获,因此加密数据至关重要。否则,任何拥有 Wireshark 和 AirPcap 的人都可以看到这些数据。
注意
当使用另一层加密(如 SSL 或 SSH)时,流量仍将在该层进行加密,且使用数据包嗅探器的人仍然无法读取用户的通信内容。
用于保护通过无线网络传输的数据的最初首选方法是按照有线等效隐私(WEP)标准进行的。WEP 在多年里略微成功,直到其加密密钥管理中暴露出多个弱点。为了提高安全性,创建了新的标准,其中包括 Wi-Fi 受保护访问(WPA)和更安全的 WPA2 标准。尽管 WPA 和 WPA2 也有缺陷,但它们被认为比 WEP 更安全。
在本节中,我们将查看一些 WEP 和 WPA 流量,并展示失败的认证尝试示例。
成功的 WEP 认证
3e80211_WEPauth.pcapng
文件3e80211_WEPauth.pcapng包含一个成功连接到启用了 WEP 的无线网络的示例。该网络的安全性是通过 WEP 密钥进行设置的。这是一个你必须提供给 WAP(无线接入点)的密钥,用以进行认证并解密从该点发送的数据。你可以将这个 WEP 密钥看作是无线网络密码。
如图 13-11 所示,捕获文件从 WAP(28:c6:8e🆎96:16)向无线客户端(ac:cf:5c:78:6c:9c)发出的挑战开始,发生在数据包 3 ➊中。此挑战的目的是确定无线客户端是否拥有正确的 WEP 密钥。您可以通过展开 802.11 头部及其标记参数来查看此挑战。
无线客户端做出响应,如图 13-12 所示,通过使用 WEP 密钥解密挑战文本 ➊,并将其返回给 WAP,数据包 4 中发送。WEP 密钥是用户在尝试连接到无线网络时提供的。

图 13-11:WAP 向无线客户端发出挑战文本。

图 13-12:无线客户端将未加密的挑战文本返回给 WAP。
WAP 在数据包 5 中响应无线客户端,如图 13-13 所示。响应中包含通知,表明认证过程已成功完成 ➊。

图 13-13:WAP 提醒客户端认证成功。
最后,在认证成功后,客户端可以传输关联请求,接收确认,并完成连接过程,如图 13-14 所示。

图 13-14:认证过程后跟随简单的两数据包关联请求和响应。
WEP 认证失败
3e80211_WEPauthfail.pcapng.
在我们的下一个示例中,用户输入 WEP 密钥以连接到 WAP。几秒钟后,无线客户端工具报告无法连接到无线网络,但没有告知原因。生成的文件是3e80211_WEPauthfail.pcapng。
与成功的尝试一样,此通信始于 WAP 在数据包 3 中向无线客户端发送挑战文本。在数据包 4 中,无线客户端使用用户提供的 WEP 密钥发送其响应。
此时,我们预计会看到认证成功的通知,但在数据包 5 中看到的是不同的内容,如图 13-15 所示 ➊。

图 13-15:此消息告诉我们认证未成功。
此消息告诉我们,无线客户端对挑战文本的响应不正确,提示客户端用于解密文本的 WEP 密钥也必定是错误的。因此,连接过程失败。必须使用正确的 WEP 密钥重新尝试连接。
WPA 认证成功
3e80211_WPAauth.pcapng
WPA 使用与 WEP 完全不同的认证机制,但它仍然依赖用户在无线客户端中输入密钥以连接到网络。一个成功的 WPA 认证示例可以在文件3e80211_WPAauth.pcapng中找到。
该文件的第一个数据包是来自 WAP 的信标广播。展开该数据包的 802.11 头部,查看标签参数,并展开“Vendor Specific”标题,如图 13-16 所示。你应该能看到一个部分,专门用于显示 WAP 的 WPA 属性 ➊。这可以让我们知道 WAP 支持的 WPA 版本和实现情况(如果有的话)。

图 13-16:这个信标让我们知道 WAP 支持 WPA 认证。
一旦信标被接收,无线客户端(ac:cf:5c:78:6c:9c)在数据包 2 中广播一个探测请求,该请求被 WAP(28:c6:8e🆎96:16)接收,并在数据包 3 中作出回应。之后,认证和关联请求与响应在数据包 4 到 7 之间生成。这些类似于我们在早期 WEP 示例中看到的认证和关联数据包,但此时没有挑战和响应发生。那个交换接下来会发生。
真正开始加速的时刻是在数据包 8。此时 WPA 握手开始,持续到数据包 11。在握手过程中,WPA 的挑战和响应发生,如图 13-17 所示。

图 13-17:这些数据包是 WPA 握手的一部分。
有两个挑战和响应。每个可以根据 802.1x 身份验证头下的重放计数器字段互相匹配,如图 13-18 所示。注意,前两个握手数据包的重放计数器值为1 ➊,而后两个握手数据包的重放计数器值为2 ➋。

图 13-18:重放计数器字段帮助我们配对挑战和响应。
在 WPA 握手完成且认证成功后,数据开始在无线客户端和 WAP 之间传输。
注意
这个示例来自于使用 TKIP 加密的 WPA 的 WAP。TKIP 只是 WLAN 上加密数据的一种方法。还有许多其他类型的加密,不同的接入点将支持不同的技术。使用不同加密方法或 WPA 版本的 WAP,在数据包层面上可能会表现出不同的特征。你可以阅读与所使用技术相关的 RFC 文档,以便更好地解读连接序列应如何呈现。
WPA 认证失败
3e80211_WPAauthfail.pcapng
与 WEP 类似,我们将看看当用户输入 WPA 密钥并且无线客户端工具报告无法连接到无线网络,但没有指示问题时发生了什么。生成的文件是3e80211_WPAauthfail.pcapng。
捕获文件的开始方式与显示成功 WPA 认证的文件相同,并包括探测、认证和关联请求。WPA 握手从第 8 个数据包开始,但在这种情况下,握手数据包有八个,而不是我们在成功认证尝试中看到的四个。
数据包 8 和 9 代表 WPA 握手中看到的前两个数据包。然而,在这种情况下,客户端发送回 WAP 的挑战文本是不正确的。因此,序列在数据包 10 和 11、12 和 13 以及 14 和 15 中重复,如图 13-19 所示。每个请求和响应可以通过重放计数器值进行配对。

图 13-19:此处额外的 EAPoL(局域网扩展认证协议)数据包表明 WPA 认证失败。
一旦握手过程尝试并失败四次,通信将被中止。如图 13-20 所示,无线客户端在第 16 个数据包中从 WAP 断开认证➊。

图 13-20:在 WPA 握手失败后,客户端断开认证。
最终思考
尽管无线网络仍然被认为有些不安全,除非附加了大量额外的安全机制,否则这一担忧并没有减缓它们在各种组织环境中的部署。由于无线通信已经成为新常态,能够捕获并分析无线网络以及有线网络上的数据变得至关重要。本章所教授的技能和概念并非详尽无遗,但它们应该为理解使用数据包分析进行无线网络故障排除的复杂性提供一个起点。
第十四章:A
进一步阅读

虽然本书中您主要使用的工具是 Wireshark,但在进行数据包分析时,无论是进行一般故障排除、网络慢速、安全问题还是无线网络问题,许多其他工具都会派上用场。本附录列出了一些有用的数据包分析工具和其他学习资源。
数据包分析工具
让我们来看看我发现的一些有用的数据包分析工具。
CloudShark
CloudShark(由 QA Café 开发)是我最喜欢的用于存储、索引和排序数据包捕获的工具。CloudShark 是一个商业的 Web 应用程序,作为一个数据包捕获库,允许您为数据包捕获添加标签以便快速引用,并在捕获文件中添加注释。它甚至提供了一些类似于 Wireshark 的分析功能(图 A-1)。

图 A-1:用 CloudShark 查看示例捕获文件
如果您或您的组织维护大量的数据包捕获,或者像我一样总是丢失文件,那么 CloudShark 可以帮忙。我在我的网络中部署了 CloudShark,并用它来存储和组织这本书中的所有数据包捕获。您可以在 www.cloudshark.org/ 了解更多关于 CloudShark 的信息。
WireEdit
您可能需要创建特定格式的数据包来支持入侵检测系统测试、渗透测试或网络软件开发。一种选择是重新创建一个生成所需数据包的场景,但这样做可能会非常耗时。另一种方法是找到一个相似的数据包,并手动编辑它以满足您的需求。我最喜欢的工具是 WireEdit,这是一款图形化工具,允许您编辑数据包中的特定值。它的用户界面非常直观,类似于 Wireshark。WireEdit 甚至会重新计算数据包的校验和,以确保您的数据包在 Wireshark 中打开时不会显示为无效。您可以在 wireedit.com/ 了解更多关于 WireEdit 的信息。
Cain & Abel
在第二章中讨论的 Cain & Abel 是一个相当不错的 Windows 工具,用于 ARP 缓存中毒。Cain & Abel 实际上是一个功能非常强大的工具套件,您肯定还能找到其他用途。它可以从 www.oxid.it/cain.html 下载。
Scapy
Scapy 是一个非常强大的 Python 库,您可以在其环境中通过命令行脚本创建和操作数据包。简单来说,Scapy 是目前最强大且灵活的数据包构建应用程序。您可以在 www.secdev.org/projects/scapy/ 阅读更多关于 Scapy 的信息,下载它,并查看示例 Scapy 脚本。
TraceWrangler
数据包捕获包含了关于你的网络的大量信息。如果你需要与供应商或同事共享网络中的数据包捕获,可能不希望他们看到这些信息。TraceWrangler 通过提供匿名化不同类型地址的功能,帮助解决这个问题。它还有一些其他功能,比如编辑和合并捕获文件,但我主要用它来进行数据包捕获的消毒处理。你可以在 www.tracewrangler.com/ 下载 TraceWrangler。
Tcpreplay
每当我有一组需要重新传输的数据包,以查看设备对其反应时,我就使用 Tcpreplay。这个工具专门用于重新传输数据包捕获文件中的数据包。你可以从 tcpreplay.synfin.net/ 下载它。
NetworkMiner
NetworkMiner 是一款主要用于网络取证的工具,但我发现它在许多其他场合也非常有用。虽然它可以用来捕获数据包,但它的真正优势在于解析数据包捕获文件。NetworkMiner 会将 PCAP 文件拆解成检测到的操作系统和主机之间的会话。它甚至允许你直接从捕获中提取传输的文件(图 A-2)。所有这些功能在免费版本中都可以使用;商业版则提供了一些其他有用的功能,如执行操作系统指纹识别、将结果与白名单进行对比,以及提高数据包捕获处理的速度。NetworkMiner 可以免费下载,网址是 www.netresec.com/?page=NetworkMiner。

图 A-2: 使用 NetworkMiner 检查数据包捕获中的文件
CapTipper
我希望你在本书中学到的一件事是,找到所需的答案通常涉及以不同的方式查看相同的数据。CapTipper 是一款专为分析恶意 HTTP 流量的安全从业人员设计的工具(见 图 A-3)。它提供了一个功能丰富的 shell 环境,允许用户互动式地探索个别会话,以找到重定向、文件对象和恶意内容。它还提供了一些方便的功能,帮助与发现的数据进行交互,包括提取压缩数据和将文件哈希提交到 VirusTotal。你可以在 www.github.com/omriher/CapTipper/ 下载 CapTipper。

图 A-3: 使用 CapTipper 分析基于 HTTP 的恶意软件传输
ngrep
如果你熟悉 Linux,肯定用过 grep 来搜索数据。ngrep 类似,它允许你对数据包捕获数据进行非常具体的搜索。当捕获和显示过滤器无法完成任务或者变得过于复杂时,我通常会使用 ngrep。你可以在ngrep.sourceforge.net/上了解更多关于 ngrep 的信息。
libpcap
如果你打算进行高级数据包解析或创建处理数据包的应用程序,你将会非常熟悉 libpcap。简而言之,libpcap 是一个用于网络流量捕获的可移植 C/C++库。Wireshark、tcpdump 以及大多数其他数据包分析应用程序在某种程度上都依赖于 libpcap 库。你可以在www.tcpdump.org/上了解更多关于 libpcap 的信息。
Npcap
Npcap 是 Nmap 项目为 Windows 开发的数据包嗅探库,基于 WinPcap/libpcap。报告显示,它在捕获数据包时能够提升性能,并提供额外的安全功能,限制数据包捕获仅对管理员开放,并利用 Windows 用户账户控制。Npcap 可以作为 WinPCap 的替代品安装,并与 Wireshark 一起使用。你可以在这里了解更多信息:www.github.com/nmap/npcap/
hping
hping 是一个非常多功能的工具,值得拥有。hping 是一个命令行数据包创建、编辑和传输工具。它支持多种协议,并且使用起来非常快速和直观。你可以从www.hping.org/下载 hping。
Python
Python 不是一款工具,而是一种值得一提的脚本语言。当你熟练掌握数据包分析时,你会遇到没有现成的自动化工具能够满足你需求的情况。在这些情况下,Python 是制作能够处理数据包并实现有趣功能的工具的首选语言。你还需要学一些 Python 来与 Scapy 库进行交互。我最喜欢的在线学习 Python 的资源是流行的Learn Python the Hard Way系列,你可以在这里找到它:www.learnpythonthehardway.org/
数据包分析资源
从 Wireshark 首页到课程和博客,许多关于数据包分析的资源都可以找到。我将在这里列出我最喜欢的一些资源。
Wireshark 首页
关于 Wireshark 的所有资源中,最重要的就是它的首页,www.wireshark.org/。这里有软件文档的链接、一个非常有用的 Wiki,包含示例捕获文件,以及 Wireshark 邮件列表的注册信息。你也可以访问ask.wireshark.org/,在那里可以询问你在 Wireshark 中看到的内容或特定功能。这个社区非常活跃且乐于助人。
实用的数据包分析在线课程
如果你喜欢这本书,你可能也会喜欢与之配套的在线培训课程。在《实用数据包分析》课程中,你可以通过视频跟随我一起分析本书及其他几本书中的所有数据包。我还提供了数据包实验室,你可以在其中测试你的技能,还有一个讨论论坛,帮助你在学习过程中与其他学生互动。这门课程将在 2017 年中推出。你可以在* www.chrissanders.org/training/*了解我的培训内容,并注册我的邮件列表,获取培训机会的通知,地址是: www.chrissanders.org/list/。
SANS 的安全入侵检测深入课程
SANS SEC503:入侵检测深入课程专注于数据包分析的安全方面。即使你不专注于安全,课程的前两天也能为你提供一个出色的数据包分析和 tcpdump 介绍。该课程每年在全球多个地点的现场活动中举办多次。
你可以在 www.sans.org/ 了解更多关于 SEC503 和其他 SANS 学院课程的信息。
Chris Sanders 的博客
我偶尔会撰写与数据包分析相关的文章,并将其发布在我的博客上,地址是 www.chrissanders.org/。我的博客也是一个门户,链接到我写的其他文章和书籍,并提供我的联系信息。你还会找到本书及其他书籍中包含的数据包捕获链接。
Brad Duncan 的恶意软件流量分析
我最喜欢的与安全相关的数据包捕获资源是 Brad Duncan 的恶意软件流量分析(MTA)网站。Brad 每周多次发布包含真实感染链的数据包捕获。这些数据包完整地包含相关的恶意软件二进制文件,并附有描述发生了什么的说明。如果你想获得分析恶意软件感染的经验,并了解当前的恶意软件技术,可以从下载一些这些数据包并尝试理解它们开始。你可以访问 MTA 网站 www.malware-traffic-analysis.net/,或者在 Twitter 上关注 Brad @malware_traffic,及时获得他的更新提醒。
IANA 的网站
互联网号码分配局(IANA),网址为 www.iana.org/,负责北美的 IP 地址分配和协议号码分配。它的网站提供了一些有价值的参考工具,例如查找端口号、查看与顶级域名相关的信息,并浏览配套网站以查找和查看 RFC。
W. Richard Stevens 的 TCP/IP 图解系列
被大多数人视为 TCP/IP 圣经的 W·理查德·史蒂文斯的《TCP/IP 插图》系列(Addison-Wesley,1994-1996)是大多数在数据包层面工作的人书架上的必备书籍。这些是我最喜欢的 TCP/IP 书籍,在写这本书时,我参考了这些书籍很多。与 Keven R. Fall 博士合著的第一卷第二版于 2012 年出版。
TCP/IP 指南
查尔斯·科齐耶罗克的《TCP/IP 指南》(No Starch Press,2005)是另一本有关 TCP/IP 协议信息的参考资源。全书超过 1600 页,非常详细,并包含许多适合视觉学习者的精彩图表。
第十五章:B
数据包导航

在本附录中,我们将研究数据包的表示方式。我们将查看完全解释的表示法和十六进制表示法,以及如何使用数据包图解来读取和引用数据包值。
因为你会发现有大量的软件可以为你解释数据包信息,你可以在不理解本附录内容的情况下进行数据包嗅探和分析。但是,如果你花时间学习数据包数据及其结构,你将能够更好地理解像 Wireshark 这样的工具展示给你的内容。你和正在分析的数据之间的抽象越少,效果就越好。
数据包表示
数据包可以通过多种方式进行表示。原始数据包数据可以表示为二进制,即由 1 和 0 组成的 2 进制,例如:
0110000001010011010111000000101011000001000000000001000000000000001000110000010
110101011011100000000000000000000000000000000000000000010000001000000000001011
0110100000000000001000000110000000000000000000000010000000100000000010000000010
二进制数字表示数字信息的最低层级,其中 1 代表电信号的存在,0 代表信号的缺失。每个数字是一个比特(bit),八个比特组成一个字节(byte)。然而,二进制数据对人类来说很难阅读和解释,所以我们通常将二进制数据转换为十六进制,这是一个由字母和数字组成的 16 进制系统。同一个数据包在十六进制下是这样的:
4500 0034 40f2 4000 8006 535c ac10 1080
4a7d 5f68 0646 0050 7c23 5ab7 0000 0000
8002 2000 0b30 0000 0204 05b4 0103 0302
0101 0402
十六进制(也称为 hex)是一种数字系统,使用数字 0 到 9 和字母 A 到 F 来表示值。它是数据包表示中最常见的方式之一,因为它简洁,并且可以方便地转换为更基础的二进制表示。在十六进制中,两个字符表示一个字节,字节包含八个比特。字节中的每个字符是一个 半字节(nibble,4 个比特),最左侧的值是 高位半字节,最右侧的值是 低位半字节。以示例数据包为例,这意味着第一个字节是 45,其中高位半字节是 4,低位半字节是 5。
数据包中字节的位置采用偏移量表示,从零开始。因此,数据包中的第一个字节(45)位于位置 0x00,第二个字节(00)位于位置 0x01,第三个字节(00)位于位置 0x02,依此类推。0x 前缀表示使用了十六进制表示法。当引用跨越多个字节的位置时,额外字节的数量会在冒号后面用数字表示。例如,要引用示例数据包(4500 0034)中的前四个字节的位置,可以使用 0x00:4。这种解释在我们使用数据包图解来解析未知协议时会非常重要,参考资料见《数据包导航》中 第 330 页。
注意
我在分析数据包时看到的最常见错误是忘记从零开始计数。这很难适应,因为大多数人都被教导从一开始计数。我已经切割和解析数据包好多年了,我仍然会犯这个错误。我能给出的最佳建议是不要害怕用手指计数。你可能觉得这样做看起来很傻,但完全没有羞耻感,尤其是当它帮助你得出正确答案时。
在更高的层次上,像 Wireshark 这样的工具可以通过使用协议解析器以完全解析的方式表示数据包,接下来我们将讨论这一点。我们刚刚看到的同一个数据包在图 B-1 中已经被 Wireshark 完全解析。

图 B-1:Wireshark 解析的数据包
Wireshark 通过标签显示数据包中的信息,这些标签用于描述数据包。数据包本身并不包含标签,但它们的数据会映射到由协议标准指定的精确格式。完全解析一个数据包意味着根据协议标准读取数据并将其拆解成标注的、易于理解的文本。
Wireshark 和类似工具之所以能够完全解析数据包数据,是因为它们内置了协议解析器,这些解析器定义了协议中每个字段的位置、长度和取值。例如,图 B-1 中的数据包是根据传输控制协议(TCP)拆解的。在 TCP 内部,有带标签的字段和值。源端口是一个标签,1606 是它的十进制值。这使得在进行分析时,能够轻松找到你要查找的信息。每当这个选项对你可用时,通常是完成工作的最有效方式。
Wireshark 有成千上万的解析器,但你可能会遇到一些 Wireshark 无法解析的协议。这通常发生在那些不广泛使用的厂商特定协议或自定义恶意软件协议上。当这种情况发生时,你将只得到部分解析的数据包。这就是为什么 Wireshark 默认在屏幕底部提供原始十六进制数据包数据(见图 B-1)。
更常见的是,像 tcpdump 这样的命令行程序显示原始十六进制数据时,并没有太多的解析器。对于更复杂的应用层协议尤其如此,这些协议更难解析。因此,在使用此工具时,遇到部分解析的数据包是常见的现象。使用 tcpdump 的一个示例如图 B-2 所示。
当你处理部分解析的数据包时,你需要依赖于更基本层次的包结构知识。Wireshark、tcpdump 和大多数其他工具都能通过以十六进制格式显示原始数据包数据来实现这一点。

图 B-2:来自 tcpdump 的部分解析数据包
使用数据包图解
如我们在第一章中所学,数据包代表根据协议规则格式化的数据。由于常见协议以特定的方式格式化数据包数据,使得硬件和软件能够解释这些数据,因此数据包必须遵循明确的格式规则。我们可以通过使用数据包图来识别这种格式,并利用它来解释数据包数据。数据包图是数据包的图形表示,允许分析师将数据包中的字节映射到任何给定协议使用的字段。它源自协议的 RFC 规范文档,显示协议中存在的字段、字段长度及其顺序。
让我们再看看在第七章中看到的 IPv4 示例数据包图(为方便起见,提供在图 B-3 中)。

图 B-3:IPv4 的数据包图
在此图中,横轴表示从 0 到 31 的单独二进制位。位被分组为 8 位字节,编号从 0 到 3。纵轴也根据位和字节进行标注,每一行被划分为 32 位(或 4 字节)部分。我们通过首先从纵轴读取,确定字段所在的 4 字节部分,然后使用横轴按偏移量符号数出每个字节,来使用这些轴来计数字段的位置。第一行包含前四个字节,即字节 0 到 3,这些字节在横轴上标注相应的数字。第二行包含接下来的四个字节,即字节 4 到 7,也可以使用横轴来计数。从字节 4 开始,它是横轴上的字节 0,然后是字节 5,对应横轴上的字节 1,依此类推。
例如,我们可以确定对于 IPv4,字节 0x01 是服务类型字段,因为我们从偏移量 0 开始,然后数到字节 1。在纵轴上,前四个字节位于第一行,因此我们将使用横轴从 0 开始数到字节 1。另一个例子是字节 0x08 是生存时间字段。使用纵轴,我们确定字节 8 位于第三行,该行包含字节 8 至 11。然后我们使用横轴从 0 开始数到字节 8。由于字节 8 是该部分中的第一个字节,因此横轴列为 0,即生存时间字段。
一些字段,比如源 IP 字段,跨越多个字节,正如我们在 0x12:4 中看到的那样。其他字段则被划分为半字节。一个例子是 0x00,其中包含了版本字段的高位半字节和 IP 头部长度的低位半字节。字节 0x06 则包含了更细粒度的内容,使用单独的比特来表示特定的字段。当一个字段是单一的二进制值时,它通常被称为标志。例如,IPv4 头部中的保留字段、禁止分段字段和更多分段字段。一个标志只能有二进制值 1(真)或 0(假),因此当值为 1 时,标志被“设置”。标志设置的确切含义将根据协议和字段的不同而有所变化。
让我们看一下图 B-4 中的另一个示例(你可能会认出这个图来自第八章)。

图 B-4:TCP 数据包图
这张图展示了 TCP 头部。通过查看这张图,我们可以回答很多关于 TCP 数据包的问题,而不需要确切了解 TCP 的工作原理。考虑一下这里以十六进制表示的一个示例 TCP 数据包头:
0646 0050 7c23 5ab7 0000 0000 8002 2000
0b30 0000 0204 05b4 0103 0302 0101 0402
使用数据包图,我们可以定位并解释特定的字段。例如,我们可以确定以下内容:
• 源端口号位于 0x00:2,十六进制值为 0646(十进制:1606)。
• 目标端口号位于 0x02:2,十六进制值为 0050(十进制:80)。
• 头部长度位于数据偏移字段中的高位半字节 0x12,十六进制值为 8。
让我们通过解析一个神秘数据包来应用这些知识。
解析神秘数据包
在图 B-2 中,我给你展示了一个仅部分解析的数据包。你可以通过解析的部分数据得知,这是一个在同一网络上两个设备之间传输的 TCP/IP 数据包,但除此之外,你对传输的数据并不了解。以下是数据包的完整十六进制输出:
4500 0034 8bfd 4000 8006 1068 c0a8 6e83
c0a8 6e8a 081a 01f6 41d2 eac6 e115 3ace
5018 fcc6 0032 0000 00d1 0000 0006 0103
0001 0001
快速统计后发现,这个数据包有 52 字节。IP 数据包图告诉我们,IP 头部的正常大小是 20 字节,这可以通过查看 0x00 的低位半字节中的头部大小值来确认。TCP 头部的数据包图告诉我们,如果没有额外选项(这里没有,我们将在第八章中更深入地讨论 TCP 选项),它的大小也是 20 字节。这意味着输出的前 40 字节与已经解析的 TCP 和 IP 数据相关。剩下的 12 字节是未解析的。
00d1 0000 0006 0103 0001 0001
如果没有了解如何解析数据包的知识,这可能会让你感到困惑,但现在你知道如何将数据包图解应用于未解释的字节。在这种情况下,解释后的 TCP 数据告诉我们该数据的目标端口是 502。回顾流量使用的端口并不是识别未解释字节的万无一失的方法,但它是一个很好的起点。快速的 Google 搜索显示端口 502 最常用于 TCP 上的 Modbus,这是一个在工业控制系统(ICS)网络中使用的协议。我们可以通过将十六进制输出与 Modbus 的数据包图解进行比较来验证这一点,如 图 B-5 所示。

图 B-5:Modbus over TCP 数据包图解
该数据包图解是基于 Modbus 实现指南中的信息创建的: www.modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf。这告诉我们应该有一个包含在 0x04:2 位置(相对于头部开始处)的长度字段的 7 字节头部。数到该位置时,我们得到了十六进制值 0006(或十进制值 6),这表明该字段后应该有 6 个字节,情况确实如此。看起来这确实是 Modbus over TCP 数据。
通过将数据包图解与完整的十六进制输出进行比较,可以得出以下信息:
• 事务标识符位于 0x00:2,并具有 00d1 的十六进制值。此字段用于将请求与响应配对。
• 协议标识符位于 0x02:2,并具有 0000 的十六进制值。这标识该协议为 Modbus。
• 长度位于 0x04:2,并具有 0006 的十六进制值。这定义了数据包的长度。
• 单元标识符位于 0x06,并具有十六进制值 01。用于系统内部路由。
• 功能代码位于 0x07,并具有 03 的十六进制值。这是读取保持寄存器功能,用于从系统中读取数据值。
• 基于功能代码值为 3,预计会有两个数据字段。参考号和字计数位于 0x08:4,每个字段的十六进制值为 0001。
现在,可以在 Modbus 协议的上下文中完全解释这个神秘的数据包。如果你正在排查负责该数据包的系统,这些信息应该就是你继续进行的全部所需。即使你从未遇到过 Modbus,这也是如何使用数据包图解来处理未知协议和未解释数据包的一个例子。
最好的做法是时刻意识到自己与正在分析的数据之间的抽象层次。这有助于你做出更合理、更有知识依据的决策,并能在各种情境中处理数据包。我自己就曾多次只能使用基于命令行的工具,如 tcpdump,来分析数据包。由于这些工具大多缺乏对许多第七层协议的解析,因此能够手动解析数据包中的特定字节变得至关重要。
注意
有位同事曾经在一个高度安全的环境中帮助进行事件响应。他被允许查看需要分析的数据,但不能访问存储数据的具体系统。在他们拥有的时间内,他们唯一能做的事情就是打印出特定对话的包。多亏了他对数据包构建方式和如何浏览它们的基本知识,他能够在打印出的数据中找到所需的信息。当然,这个过程比冷糖浆顺着冰冻的树枝流下来还要慢。这是一个极端的例子,但它是为什么普遍的、与工具无关的知识如此重要的最佳证明。
基于上述原因,花时间拆解数据包,以获得查看多种解读的经验,是非常有帮助的。我自己做得足够多,以至于打印出了几种常见的数据包图示,并将它们塑封,放在桌子旁边。我还在我的笔记本和手机上保留了数字版本,以便在旅行时快速查阅。为了方便起见,我已将几种常见的数据包图示包含在与本书相关的 ZIP 文件中,该文件包含了数据包捕获内容(* www.nostarch.com/packetanalysis3/*)。
总结思考
在本附录中,我们学习了如何以多种格式解读数据包数据,并且如何使用数据包图示来浏览未解读的数据包。掌握了这些基本知识后,无论你使用什么工具来查看数据包数据,都应该能够顺利地解剖数据包。











浙公网安备 33010602011771号