在开发网络应用时,能够准确地看到通过网络传输的内容通常很有用。可能是您的框架出现了一些奇怪的情况,您试图发现浏览器的用户代理,或者您想看看 IP 协议或更低层中发生了什么。我们可以使用一类称为包嗅探器的工具来完成这项工作。
数据包嗅探器设计用于捕获进入和离开计算机的所有网络流量,允许我们查看程序发送和接收的所有数据包的完整原始内容,以及堆栈上所有协议的所有头和有效负载。
我们将快速查看其中一个应用。它不仅为我们提供了一个非常有用的网络编程调试工具,它还为您提供了网络流量结构的直观视图,并让您更好地理解分层和封装的概念。
在我们开始之前,先说一句小心谨慎的话;如果您在非自己的网络上使用计算机,例如在您的工作或学习地点,则在运行数据包嗅探器之前,应获得网络管理员的许可。在使用网络集线器而不是交换机的网络上,嗅探器可能会捕获发送给您自己以外的计算机的数据。此外,运行数据包嗅探器可能违反网络的使用策略。即使不是这样,数据包嗅探器也是功能强大的网络监控工具,管理员通常喜欢在使用它们时注意它们。
如果这很困难,不要惊慌!这本书不依赖于在任何时候都可以访问数据包嗅探器;我们只是认为,在为网络编程时,您会发现它们非常方便。
我们要看的程序叫做Wireshark。它是一个开源的包嗅探器,支持解释各种网络协议。
对于 Windows 和 Linux,Wireshark 可从下载 http://www.wireshark.org 。在 Debian、Ubuntu、RHEL、CentOS 和 Fedora 上,它作为wireshark
包提供。
您需要具有 root 或管理员访问权限才能安装此软件。在 Windows 上,如果WinPcap
库要求您安装或更新,请确保您安装或更新了该库,并允许它在引导时在提示时启动WinPcap
驱动程序。
在 Debian 和 Ubuntu 上,您需要配置 Wireshark 以允许普通用户运行捕获。运行以下命令:
$ sudo dpkg-reconfigure wireshark-common
说Yes
到Should non-superusers be able to capture packets?
注意,这并不自动允许所有非超级用户使用 Wireshark,他们仍然需要添加到wireshark
组。现在为您自己的用户执行此操作,例如:
$ sudo usermod -aG wireshark myuser
您可能需要注销并再次登录才能使其生效,甚至可能需要重新启动。对于其他 Linux 发行版,请查看其文档,或者 Wireshark wiki 上有关于在分配这些权限的说明 http://wiki.wireshark.org/CaptureSetup/CapturePrivileges 。
如果您在任何时候遇到问题,您可以在的 wiki 上获得有关安装的进一步帮助 http://wiki.wireshark.org/CaptureSetup 。
配置完成后,在 Linux 上,只需在X
会话中运行wireshark
即可启动图形界面。
安装并运行 Wireshark 后,您将看到如下窗口:
包嗅探通常分两步工作:首先,我们运行流量捕获会话,然后分析捕获的流量。在捕获过程中,Wireshark 要求操作系统提供其处理的所有网络流量的副本,然后 Wireshark 将其保存在缓冲区中供我们分析。Wireshark 为我们提供了一些工具,让我们能够过滤捕获的数据,这样我们就可以只处理我们想要的数据流,并钻取每个数据包,以便查看报头数据和有效负载。
因此,首先,我们需要选择要捕获流量的接口。我们可以看到在开始按钮下面有一个界面列表。Wireshark 捕获通过我们选择的所有接口的所有网络流量;这通常意味着我们最终捕获了很多我们实际上并不感兴趣的数据。为了减少这种干扰,最好捕获尽可能少的接口,最好只捕获一个。
我们将使用第一个 RFC 下载程序,来自第 1 章、网络编程和 Python、RFC_downloader.py
,生成一些网络流量进行分析。由于此程序与 Internet 上的主机通信,因此我们希望捕获提供 Internet 连接的网络接口。
如果您不确定哪个界面是您的 Internet 界面,则点击开始按钮上方的界面列表按钮,弹出窗口,如下图所示:
在对话框的右侧,您可以看到自我们打开窗口以来通过每个接口的数据包数量的实时计数。如果没有太多事情发生,你可以通过浏览网站来产生一些互联网流量。包数增长最快的接口将是 Internet 接口(忽略 Linux 上的any
接口)。记下接口的名称并关闭窗口。
网络接口可以以两种模式之一捕获数据包:混杂模式和非混杂模式。在混杂模式下,接口将把它接收到的所有通信量传递给嗅探器,即使它不是发送给我们的计算机的通信量。在非混杂模式下,接口过滤掉任何不适合我们计算机的流量。除非您有非常具体的原因,否则通常最好以非混杂模式运行,因为这样可以减少我们需要手动过滤的无关流量。Wireshark 默认情况下启用混杂模式。要禁用,请进入捕获|**选项。。。**并确保“在所有接口上使用混杂模式”未选中。然后检查选项窗口顶部接口列表中的“Prom 模式”列,并确保您正在捕获的接口显示为禁用。完成后,关闭选项窗口以返回主屏幕。
从主屏幕开始按钮下方的界面列表中选择您的互联网界面,点击开始开始捕捉**。**过了一两分钟,我们会看到一些包裹进来:
当 Wireshark 捕获数据包时,让我们生成一些我们感兴趣分析的流量。在终端中运行RFC_downloader.py
RFC downloader 程序下载 RFC 2324:
$ python3 RFC_downloader.py 2324
...
Network Working Group L. Masinter
Request for Comments: 2324 1 April 1998
Category: Informational
...
下载运行后,返回 Wireshark,点击工具栏上的停止按钮停止捕获。如果捕获过程中出现问题,不要担心,我们可以再试一次;只需停止捕获,然后单击工具栏中的开始新的实时捕获按钮,并在提示时不保存对上一次捕获的更改。当它运行时,再次运行RFC_downloader.py
。一旦你有一个包含 RFC 下载器流量的捕获,让我们仔细看看它。
如前一屏幕截图所示,Wireshark 捕获屏幕分为三个部分。顶部部分列出捕获的数据包,每行一个数据包,并提供每个数据包的基本信息,例如源地址和目标地址,以及数据包包含数据的最高层协议的名称。
中间部分包含所选数据包中存在的协议的细分。顶行相当于网络堆栈中的第 1 层,后续行对应于更高的层。
底部部分包含整个捕获数据包的原始列表。这分为三个主要的垂直区域。左侧第一列中的数字是从数据包开始的行开始的字节偏移量(十六进制)。中间部分由两列组成,每列有 8 个十六进制数字;本节将数据包中的每个字节显示为十六进制整数。右侧的部分由两列 ASCII 字符组成,是数据包中字节的 ASCII 表示。此处使用点,其中字节值映射到不可打印字符。
让我们看看是否能找到下载程序生成的数据包。捕获中可能有相当数量的额外网络数据,因此首先,我们需要过滤掉这些数据。
Wireshark 允许我们使用它支持的任何协议的任何属性进行过滤。要过滤,我们使用工具栏下的过滤器框。Wireshark 有一个完整的过滤语言,您可以通过帮助系统进行调查。现在,我们只需要做一些基本的查询来查找数据包。在过滤框中输入http
,点击应用按钮。这将显示的数据包限制为仅包含 HTTP 协议的数据包,如以下屏幕截图所示:
即使您在捕获会话期间故意生成的唯一 HTTP 流量是通过 downloader 程序生成的,我们也可能会看到更多的 HTTP 数据包。这是因为一些程序,例如文件云存储客户端,在后台通过 HTTP 与它们的服务进行通信的频率相当高。此外,Wireshark 目前将 SSDP 协议包标识为 HTTP,因为 SSDP 是从 HTTP 派生的。
不过没问题,我们可以改进我们的过滤器。我们的下载包的唯一识别特征是我们与之通信的服务器,www.ietf.org。如果我们查看数据包列表,您可以看到捕获的数据包的源地址和目的地址都是 IP 地址,因此在我们编写新的过滤器之前,我们需要找到www.ietf.org的 IP 地址。
检索主机名的 IP 地址称为名称解析,这正是 DNS 设计的任务。我们可以使用几种机制与 DNS 进行交互。在 Linux 和 Windows 上,我们可以使用nslookup
命令行工具。运行以下命令:
$ nslookup www.ietf.org
Server: 127.0.1.1
Address: 127.0.1.1#53
Non Authoritative answer:
www.ietf.org canonical name = www.ietf.org.cdn.cloudflare-
dnssec.net.
Name: www.ietf.org.cdn.cloudflare-dnssec.net
Address: 104.20.1.85
Name: www.ietf.org.cdn.cloudflare-dnssec.net
Address: 104.20.0.85
输出表明www.ietf.org实际上托管在两个 IP 地址上:104.20.1.85
和104.20.0.85
。随着越来越多的网站部署负载平衡和内容交付网络,将工作负载分散到服务器上,这种情况变得越来越频繁。
快速浏览我们捕获的 HTTP 数据包列表可能会让我们看到最终连接到的服务器。在前面的例子中,它是104.20.0.85
。但是,为了确保,我们可以过滤这两个 IP 地址。
请注意,nslookup
可能返回与前一示例中所示不同的 IP 地址。Web 服务可以出于各种原因更改其服务器的 IP 地址。
所以现在我们可以过滤www.ietf.org。使用刚才解析的 IP 地址,在“筛选器”框中输入此新查询:
http and (ip.addr == 104.20.1.85 or ip.addr == 104.20.0.85)
再次点击应用按钮。此查询添加了额外条件,即除了涉及 HTTP 协议外,数据包的 IP 源或目标地址必须为104.20.1.85
或104.20.0.85
。
ip.addr
语法是对协议属性进行过滤的典型示例。还有很多。例如,如果我们只想按源地址过滤,而不是同时按源地址和目标地址过滤,我们可以使用以下命令:
http and (ip.src == 104.20.1.85 or ip.src == 104.20.0.85)
要了解所有可用的协议及其属性,请单击表达式。。。过滤器箱右侧的按钮。在出现的窗口的左侧窗格中,我们可以看到列出的所有协议,我们可以通过单击相应的三角形或**+**符号展开一个协议,这将显示其属性。在此窗口中,IP 被列为IPv4
。
回到我们的 RFC 下载包,如果表达式窗口打开,让我们关闭它,并将注意力转向主窗口。应用http and (ip.addr == 104.20.1.85 or ip.addr == 104.20.0.85)
过滤器后,我们会在屏幕顶部看到两个数据包:
第一个是urlopen()
发送给服务器的 HTTP 请求,第二个是服务器的 HTTP 响应。
点击第一个包进行选择,并将注意力转向窗口的中间部分。我们可以看到五行信息。每一层都对应于网络堆栈中的一层以及该层中使用的协议。在监视屏幕底部的数据包的原始列表时,点击中间部分的不同行。您将看到原始数据包列表的不同区域被突出显示。突出显示的区域是原始数据包中与您单击的协议相关的部分。对于第一层(从帧开始的行),它突出显示整个数据包,因为整个数据包是通过导线发送的。对于最后一层超文本传输协议,它突出显示了作为 HTTP 请求的数据包部分,如前一示例所示。对于中间的层,它只突出显示该协议封装数据包的头部。
我们可以通过在中间部分中的每一个协议行的左侧点击三角形或 PoT T0+Endot1 符号来为每个封装的包钻入头数据。如果我们在超文本传输协议线路上这样做,我们会得到如下结果:
我们请求中的HTTP
头已经被 Wireshark 解释并分解,以使它们更具可读性。您可以用同样的方法浏览其他协议的数据。
让我们检查我们捕获的第二个数据包,HTTP 响应。现在在窗口顶部单击它:
你会注意到这个中间包中的一些额外的行。引用重新组装的 TCP 段的行表示 HTTP 响应实际上足够大,可以跨越四个 TCP 数据包。Wireshark 意识到了这一点,并通过组合相关的 TCP 数据包重新组装了完整的 HTTP 数据包,因此当我们点击超文本传输协议线路时,我们看到了整个 HTTP 数据包。
如果您没有看到这一点,您可能需要在“选项”菜单中将其打开。进入编辑****首选项…打开首选项窗口,然后展开屏幕左侧列表中的协议,向下滚动找到HTTP。确保选中了提及跨越多个 TCP 段的两个选项。
最后,基于行的文本数据行向我们展示了响应内容媒体类型(如第 2 章所述,HTTP 和与 Web 一起工作行),并展开该行向我们展示了响应主体的文本数据。
您可能会在浏览菜单时注意到,Wireshark 是一款功能非常丰富的网络分析仪,我们甚至还没有触及其全部功能的表面。我鼓励您在使用本书时将其放在手边,并在任何您想仔细查看通过网络发送或接收的数据的地方使用它。