乐者为王

Do one thing, and do it well.

协议分析器的威力

英文原文:http://arstechnica.com/information-technology/2016/09/the-power-of-protocol-analyzers/

问题发生在错综复杂的网络世界里。但要在一时激动之下确定一种新型问题的确切原因变得有些冒险。在这种情况下,当Google-fu耗尽的时候甚至其他能干的工程师也可能会被迫去依赖试错法。

幸运的是,有个秘密武器等待乐意的工程师去部署——协议分析器。该工具允许你明确地确定几乎任何错误的根源,给你提供在底层协议上自我学习的能力。现在唯一的问题是,许多工程师因为(毫无根据的)恐惧而完全回避它。

什么是协议分析器?

协议分析器,或者数据包嗅探器,是一个用于拦截通信量,存储它们,并以一个已解码的、人类可读的状态呈现它们的工具。现代协议分析器比如Wireshark甚至可以靠自己发现基本的问题,然后使用捕获的数据执行统计分析。

不理会特性,数据包嗅探器都以基本相同的方式工作。它们把自己插入到网络堆栈中,把所有通信量复制到一个缓冲区或文件。大部分还会将网络驱动置于“混杂模式”,该模式从根本上说允许这些工具取回所有进入网络堆栈的通信量,而不是只采集前往系统本身的通信量。

协议分析仪如何帮助

在很多情况下,解决一个困难的网络问题的最难部分是找到和理解问题的根源。这种困难的部分源于这样的事实,你对大多数问题使用的工具不是正确的对底层问题的工具。

如果你是一个系统管理员,很有可能你经常用于数据采集的工具是某种日志和错误消息。通常,这些都是解释工具。这些实体试图把原始数据总结为对非开发者或非工程师有意义的东西。因为解释工具是从应用层的视角提供问题的汇总数据,它们往往不能帮助你解决底层的问题。

例如,一条事件日志消息可以告诉你应用程序无法连接到服务器。它甚至可以告诉你根本原因是超时。但这条消息不大可能告诉你超时是由一个黑洞路由器丢弃一个大帧引起。它不能,因为事件日志消息服务不知道错误为何发生。为了使工具知道那个,它需要预测(不解释)这个非常问题,在MTU稳步减少的情况下发送数据包,直到一个通过。如果一个事件日志消息服务早就被编写好要做那件事,从一开始你就不会有这个问题。

当使用错误的工具时,你可能会在某处花上几个小时甚至几周的时间,直到你侥幸得到解决方案。然而,通过使用协议分析器和历久弥新的ping命令,你可以非常容易地在大约5分钟内诊断这个问题。就像早在高中时我的汽车技术辅导员就告诉我的,它全都是关于对任务使用恰当的工具。

除了确定错误,协议分析器提供为数不多的方法之一去证实问题的根源。以前我在微软的时候,棘手问题在团队间来回穿梭是很常见的,因为每个组误解由解释工具提供的数据。首先,问题可能被发送到Exchange团队,接着它可能被穿梭到Active Directory团队,然后最后到Networking团队。

通常,这是因为在其它团队的能力范围之内一个问题好像是合理的。然而,烫手山芋的游戏往往停止在Networking团队。为什么?因为Networking团队的头号工具是证实问题根源的救世主。

网络,像所有的计算,其核心是完全合乎逻辑的。一旦你了解它在幕后是如何工作的,你就有能力在底层确定问题,不论问题是多么独特。作为协议分析的一个伟大副作用,你也将学到很多关于网络的知识,它们将帮助你解决各种各样的网络问题(即使那些不需要协议分析)。

Wireshark基础

现在,有各种各样的协议分析器可供选择,从免费的和相当功能的微软消息分析器到特性极其丰富但十分昂贵的Savvius Omnipeek。多年来我已经使用过大量的分析器,但我最喜欢的用于常规故障排除的协议分析器是Wireshark。它是免费的,开源的,多平台的具有很多特性的分析器。有个充满活力的社区站在它背后,而且Wireshark也相当容易习惯。这让它成为一个很好的开始的地方。

你可以从 https://www.wireshark.org/ 下载用于你操作系统的Wireshark。安装它没有什么特别的,但如果你是安装在Windows上,确保也安装了捆绑的WinPCAP驱动程序。这允许Wireshark实际上捕获数据包(没有它,你只能观看存档的数据包)。

Wireshark通常将你的NIC置于混杂模式。正常情况下,你的NIC只会保留前往你的MAC或者广播MAC(FF-FF-FF-FF-FF-FF)的帧。启用混杂模式后,不管怎样,你的NIC保留所有它听到的帧。

从理论上讲,这意味着你应该接收所有的在你Ethernet段上的数据包。不过,实际上如今几乎所有的Ethernet网络都是交换网络。如果你想接收所有的通信量,必须多做些工作。

一旦你已经安装了Wireshark,使用它是相当简单的。把它打开,你将看到如下显示的屏幕:

这个屏幕给你展示选择一个在它上面捕获数据包的NIC的选项和输入一个用于只捕获一部分入站数据包的过滤器的选项。如果你选择一个NIC然后点击在文件菜单下面的小鱼翅图标,Wireshark将立即开始捕获数据包。

随着数据包被捕获,Wireshark在主界面中实时地显示它们。当你准备停止时,你只需点击在鱼翅图标旁边的小红方块。

数据包列表部分显示在这个点捕获的每件事物,按它们被捕获的顺序排序(默认)。(你可以通过点击要作为排序依据的标题任意地排序这些数据包。)

数据包细节部分显示Wireshark解码的在数据包中的每个报头。基本上,Wireshark有几乎今天在用的每个协议的解码器,并且为了显示分成字段的数据,解码器工具自动应用到每个数据包。

举例来说,如下,我已经为一个典型的HTTP数据包增加了Ethernet II报头。

你可以清楚地看到Wireshark已经析出了Destination和Source的MAC地址,以及Type字段,它是0x0800。Type字段指出下个报头应该是一个IPv4报头,Wireshark很方便告诉你这个。

这个解码特性使你不必自己计算字节和解码它(不过,如果你愿意,你仍然还可以在原始字节部分做)。如果对原始字节部分有兴趣:Wireshark同时为所有数据提供ASCII转换,它有时提供令人惊讶的数据。在下图,你可以在ASCII视图里的这个数据包中清楚地看到HTTP请求发送的细节。

Wireshark同时也提供一些非常实用的分析和统计特性,包括测量响应时间和往返时间的能力。但到目前为止,最有用的特性是过滤功能。

在数据包列表直接的上方是一个文本框,那里你可以输入显示过滤器。默认不使用过滤器,意味着显示被捕获的所有数据包。然而,你经常最后得到信息过载,而过滤掉噪音是数据包分析的一个非常重要的部分。

Wireshark中的过滤器按照一门简单的语言结合协议字段、比较运算符和逻辑运算符以便过滤掉不匹配条件的数据包。例如,过滤器http将只显示HTTP通信量,而过滤器ip.addr == 192.168.1.10将只显示源或目标的IP地址是192.168.1.10的数据包。

当你是第一次开始的时候,过滤可能会有点令人生畏,但通常在Wireshark中学习过滤器的最简单的方法是使用内建的表达式工具。可以通过点击过滤器文本框右边的Expression按钮访问它。

这个工具允许你寻遍Wireshark本身支持的所有协议,挑选你想过滤的字段而不需要知道过滤器动词或语法。只需选择协议,填写呈现的字段,然后过滤器将会为你而建。这里,我使用表达式工具构建一个仅查找Ethernet广播的过滤器。

注意工具如何在底部的绿框中显示最终的过滤器语法。通过注意这个字段,你将最终变得熟悉你的最常用的过滤器。

然而,你不能用表达式工具做的一件事是把过滤器串起来。因为那个原因,你需要学习一些逻辑运算符。Wireshark的基本逻辑运算符是and(&&)、or(||)和not(!)。

and被用于结合过滤器,只有满足所有条件的数据包会被显示。例如,过滤器http && ip.addr == 192.168.1.10将只显示在第7层报头中的HTTP协议和在IP报头中的IP地址192.168.1.10两者都包括的数据包。

or被用于查找两者中的任何一个过滤器,因此满足你输入的任何条件的数据包都会被显示。举例来说,过滤器http || ip.addr == 192.168.1.10将显示在第7层报头中的HTTP协议或在IP报头中的IP地址192.168.1.10的数据包。

not被用于从结果中过滤掉一些东西。例如,过滤器ip.addr == 192.168.1.10 ! http将显示有在IP报头中的IP地址192.168.1.10但没有在第7层报头中的HTTP协议的数据包。

关于基本的Wireshark功能最后要注意的事是,除保存你的原始捕获外,你也有多种多样的选项导出捕获。

首先,你导出当前选择的数据包、所有数据包、你标记的数据包或者一段范围的数据包。在这些选项的每一个中,你可以选择导出所有被捕获的数据包或只是被显示的数据包(考虑当前应用的过滤器)。这些选项让你非常具体地知道你想导出哪些数据包。

此外,你可以把数据包导出成几乎任何常用的格式。在Wireshark中用于文档和电子邮件转出的最好的特性之一是以纯文本或CSV格式导出解剖数据包(完整的数据包解码)的能力。要做到这个,只需从文件菜单里选择“Export Packet Dissections”。

理解你所看到的

尽管所有这些功能都很好,底线是如果你不明白在每个报头中字段的目的它们都是无用的。幸运的是,除了少量专有协议,你遇到的几乎每个协议的规格说明都是免费在线的。

例如:Ethernet,你可以直接到IEEE下载标准;802.3标准可以在 http://standards.ieee.org/about/get/802/802.3.html 获得。它是免费的直接来自权威人士。如果你在查找802.3 Ethernet帧格式,你将发现真的只有3个感兴趣的字段:目标MAC地址、源MAC地址和类型/长度字段。下图中在Wireshark解剖体左边的是来自IEEE 802.3规格说明Section 1中Part 3.1.1的Figure 3-1:

如果你想知道preamble和SFD发生了什么,它们在帧从NIC到Wireshark向上传递给栈之前被移除。同样地,你通常不会在末尾看到FCS,因为它在向上传递帧之前被剥去。

在第2层上面,所有TPCTCP/IP协议由IETF管理和由RFCs(请求评论)定义。所有这些RFCs可以在站点 https://www.rfc-editor.org/ 上即刻地免费地获得。虽然它们有点简洁(并且因为这个原因有时难以理解),它们总是正确的,具体问题的澄清可以使用Google快速搜索获得。

举例来说,通常混淆新手的事情之一是大量TCP重置,或者在TCP报头中数据包有打开的RST标记。浏览RFC 793(TCP),你可能会得到RST总是用信号告知一些坏事情的印象。几乎所有的35个左右提到的RST与某种错误条件有关联。

然而,使用关键词“tcp rst from client”的Google快速搜索将让你得到大量的关于这个现象的很好的讨论。也许最好的是来自Wireshark论坛,在那里他们解释说这很平常,因为客户端应用仅仅被编码去重置链接而不是优雅地关闭它。在这种情况下,服务端已经发送一个FIN。作为回复一个FIN/ACK并等待最终的ACK的替换,客户端只需通过发送一个RST并中止会话来优化过程。在下面的示例中这可以清楚地被看到。

除了规格说明和Google,另一个学习协议通常如何运转的良好来源是示例跟踪的资料库。这些示例跟踪允许你去查看相当典型的既常见又晦涩的协议操作,以及一些十分罕见的平常可能不会碰到的错误。

一个很好的起点是Wireshark Wiki上的样板捕获:https://wiki.wireshark.org/SampleCaptures 。在这里有大量非常有用的捕获让你去下载以及用过滤和其它Wireshark特性做实验,包括像广播风暴、病毒和攻击套装这样有意思的错误。如果这些还不够,在这个页面上还有一些其它资源的链接去协助你。但是毫无疑问地,变得擅长协议分析的最快方式是仔细观看大量的捕获并试图理解被使用的协议。

如何得到好的捕获

如果不能捕获正确的数据,世界上所有的领悟都无济于事。在最基本的层面,目标是只捕获涉及你试图解决的问题的数据包,有效减少你跟踪里的噪音。

为了做到这点,你可以使用一个捕获过滤器去从捕获中排除那些匹配过滤器外的所有数据。如果你确切地知道你在寻找什么这会工作的很好,但往往这种方法会导致你不能觉察一些重要的事情。大多数时候你只有一个问题是什么的粗略想法,或者你忘了一些潜在的找到错误的关键的过程。如果这种情况发生,使用捕获过滤器就没那么幸运,而且你不能返回和没重设置它就不过滤捕获。

例如,在诊断一个网站的性能问题时,你可能决定使用一个捕获过滤器集从Web服务器自身取得捕获,以便只捕获在其与客户端系统和后台SQL服务器之间往返的数据。然而,这个问题实际上可能仅仅是Web服务器使用的身份验证服务器过载,等待身份验证才是引起整个性能问题的原因。使用你选择的捕获过滤器你将永远不会发现这个问题。

这是我倾向于捕获所有数据并且使用显示过滤器去减少跟踪里的噪音的原因。这不是说捕获过滤器完全不必要。捕获过滤器的一个常见用途是当你有一个非常繁忙的你正在捕获的千兆或万兆连接的时候,捕获过滤器变得有用仅仅是因为大量的数据。不过,你始终需要牢记过滤器的限制。

得到一个好的捕获的第二部分是正确识别你需要捕获的系统。举例来说,在前面关于Web服务器性能问题的例子中,我可能首先会从Web服务器和Web客户端两者取得同时发生的捕获。这样你可以看到两边的正常预期行为的任何偏差,这有助于你将问题隔离到服务器或客户端。

一旦查明延迟是一个与身份验证有关的服务端问题,然后我会从Web服务器和身份验证服务器两者取得其它的跟踪。这样,我可以看到是本地到身份验证服务器的问题还是等待像DNS这样其它服务的问题或者Global Catalog是实际上的罪魁祸首。

得到一个好的捕获的第三步是在成功和失败条件中都使用捕获。举例来说,如果你有一个间歇性的Web服务器性能问题,设法在站点正常和不正常工作时都得到跟踪。这能给你一个好的和坏的比较跟踪,可以使用它去隔离问题。

最后,当处理一个间歇性的问题时,你会发现很难得到一个失败捕获。在这种情况下,Wireshark有一个很重要的特性被称为环形缓冲区,它允许你持续地捕获。

通常,特别在一个繁忙的网络上,持续的捕获将冒填满磁盘的风险。但有了环形缓冲区,Wireshark会写入文件直到它达到指定大小或者经过一段时间,然后它会切换到一个新文件。一旦指定数量的文件已经被写入,程序删除最旧的文件。例如,看看下面我已经定义的设置:

这个配置告诉Wireshark不管文件大小每10分钟创建一个新文件,并且确保程序保留总计3个文件,根据需要删除最旧的。这确保从错误被通知的时间起我有30分钟去停止捕获。这是一个非常有用的技术用于捕获极其间歇性的问题。

这些是你需要的以便用Wireshark开始故障排除的所有基本技术。使用这些技术和资源,你会发现你经常能用比几乎任何其它技术更短的时间找到和验证网络问题的原因。快乐的故障排除。

Comments