本文是书籍《Wireshark数据包分析实战(第3版)》第 4~5 章的学习笔记。
实践环境:macOS 12.5 ARM64
Wireshark Version: 3.6.7 (v3.6.7-0-g4a304d7ec222)
在前面的《Wireshark 入门概述》一文中,笔者对 Wireshark 这款软件做了一个简单的介绍。以此为基础,笔者将在本篇文章中总结如何利用 Wireshark 进行抓包,并利用 Wireshark 提供的功能进行相关分析。
数据包捕获
对于如何捕获数据包,在《Wireshark 入门概述》中已描述过,简单来说就两步:
- 选择需要监控的网卡
- 输入的过滤条件,只抓取想要的数据包(可省略,表示抓所有包)
然后点击回车:
上面的操作比较简单,基于此,笔者在这里将对一些高级用法进行总结。
捕获选项
在捕获之前,可以通过 “Capture - Options” 设置更多的额外捕获选项,如下图所示:
1、Input:输入
其实它就是把前面主界面的 Capture 选项进行了扩展,从而设置更多细节。
上方的列表中显示了所有的网卡列表,同时包含了相应的描述:
- Interface:网卡名称
- Traffic:网络流量图
- Link-layer Header:网卡类型
- Promiscuous:是否开启网卡混杂模式
- …
这些内容在官网[1]都有描述,大多数情况下,我们不会去改变它们,所以不做过多赘述。
需要补充一点的是网卡混杂模式,开启该模式,就能让网卡将能看到的流量都接收下来,便于网络管理员进行分析。如果不开启,那么对于网络中的广播包,只要不是发给自己的(比如 mac 地址不匹配),网卡驱动可能会将数据丢弃。现在的网卡一般都支持混杂模式,而 Wireshark 中又包含了对应的驱动,只要我们对其进行设置,便可以将网卡切换到混杂模式上。
2、Output:输出
Output 下的选项就比较好理解了,主要针对内容输出进行设置:
1)“Capture to a permanent file” 即设置或选择需要保存到本地的文件名称;
2)“Output format” 指的是文件格式,其中 pcap 为旧版本格式,pcapng 为新版本格式[2];
3)“Create a new file automatically…” 根据包的数量、大小或时间自动生成新的抓包文件,这样所有数据就不会都保存到一个文件中;
4)“Use a ring buffer with x files” 表示设置环状缓冲,当所有文件都写满以后,就覆盖最早的第一个文件。
3、Options:选项
最后的 Options 也比较简单,主要针对显示、名称解析和停止捕获进行设置。
1)Display Options:前两项一起使用,主屏会滚动显示抓取的数据包,而第三个 “Show capture information during live capture” 如果选择,则会在主屏上显示一个小屏,用来统计当前的抓包数据,如下图所示:
2)Name Resolution:链路层、网络层以及传输层的名称解析;
3)Stop capture after automatically after…:根据包的数量、大小或时间等自动停止抓包。
捕获过滤器
网络上流动的数据包成千上万,哪怕只与本机交互的数据包也非常多。如果不管三七二十一,将所有数据包都抓下来,不仅浪费大量存储空间,对整个机器的性能也有重大的影响,而且不利于后期的数据分析。
所以,在抓包之前,我们就需要通过过滤器对需要的包进行筛选,这种过滤器又被称为捕获过滤器。与之相对应的,是下文分析数据包时使用的显示过滤器。
使用捕获过滤器非常简单,在 “Capture - Options - Input” 中选择网卡,然后按照 BPF 语法编写过滤表达式即可。
1、BPF 语法
BPF 是 Berkeley Packet Filter 的缩写,由于大部分抓包软件都依赖于使用 BPF 的 libpcap/WinPcap 库,所以该 BPF 被广泛用于各类抓包软件。BPF 语法格式也比较简单:
1) 一个过滤表达式(expression)= 一个或多个原语(primitives);
2)一个原语(primitive)= 一个或多个限定词(qualifiers);
3)每个限定词后面跟着一个 ID 名字或者数字;
4)原语之间使用逻辑操作符(operators)连接。
样例如下:
该样例表达的含义为:只抓取发往 192.168.1.32 机器,端口为 80 的 tcp 协议流量。
从表达式样例可以看到:
a)逻辑操作符有 3 种:与( && ),或( || ),非(!)。
b)限定词分类:
Qualifier | Desc | Example |
---|---|---|
Type | 指出名字或数字所代表的含义 | host、net、port |
Dir | 指出传输方向是来(源头)还是去(目标) | src、dst |
Proto | 限定所要匹配的协议 | ether、ip、tcp、udp、http、ftp |
2、常用过滤器
1)地址过滤
简单来说,就是对捕捉的设备地址进行过滤,包括:MAC 地址、IPv4 地址、IPv6 地址以及 DNS 主机名等。
host 192.168.1.33
只捕获与 192.168.1.33 这个 IPv4 地址相关的流量;host 2308:8277:420:152a:819:41f0:28fa:8862
只捕获与这个 IPv6 地址相关的流量;host www.baidu.com
只捕获与域名www.baidu.com
相关的流量;ether host 52:54:99:2f:37:b1
只捕获与这个 MAC 地址相关的流量;- ……
在前面的基础上增加传输方向的限定词(src 或 dst),则用于限定是捕获流入还是流出的流量。比如 src host 192.168.1.33
,表示只捕获从主机 192.168.1.33 发过来的流量。
而 net 关键字则是对 src 或 dst 的扩展,比如可以捕获发送给某个 CIDR 子网的流量:dst net 192.168.31.0/24
,关于 net 的用法,官网[3]给出很多示例,建议阅读了解。
2)端口过滤
端口过滤比较简单,可以指定只筛选(或过滤)某个端口,示例如下:
port 8080
只捕获 8080 端口的流量,包括流入或流出的;!src port 8080
过滤掉源端口为 8080 流量,将其它流量都截下来;- ……
3)协议过滤
如果协议无法简单地通过端口等进行定义,那么可以基于特定协议进行数据包过滤,比如:
icmp
捕获 icmp 协议产生的流量;!ip6
过滤掉 IPv6 之后的流量;- ……
3、高级用法
BPF 语法除了上文提到的过滤规则外,还提供了基于数据报文的高级过滤方式,比如基于一个字节或多个字节进行逻辑判断的规则。
以 ICMP 协议为例,其前两个字节代表类型和代码(子类型)[4],比如当类型为 3,代码为 3 时表示因“目标端口不可达”引起的“目标不可达”。所以,我们可以使用如下方式进行过滤:
icmp[0]==3
只捕获“目标不可达”的网络包,从数据包起始位置偏移 0 字节;icmp[0:2]==0x0303
只捕获因“目标端口不可达”引起“目标不可达”的网络包,从数据包起始位置开始的 2 字节数据;icmp[0]==8 || icmp[0]==0
只捕获 echo 请求和回复的包;- ……
另一个常见的例子是对 TCP 协议的过滤,在介绍 TCP 三次握手时,笔者对 TCP 的头部进行了说明(如上图),其第 13 个字节(下标从 0 开始)是控制位。
FLAG | 全称 | 描述 |
---|---|---|
CWR | Congestion Window Reduced | 与下面的 ECE 都用于 IP 头部的 ECN 字段,当 ECE 标志为 1 时,通知对方已将拥塞窗口缩小 |
ECE | ECN-Echo | 置为 1 会通知对方,从对方到这边的网络有拥塞 |
URG | Urgent | 若值为 1,则表示包中有需要紧急处理的数据,更多内容请参考后面的紧急指针选项 |
ACK | Acknowledgement | 若值为 1,确认应答的字段变为有效。除了最初建立连接的 SYN 包外,该位必须设置为 1 |
PSH | Push | 若值为 1,收到应用层消息立马发送,或将收到的数据立马传给应用层;若值为 0,则先缓冲 |
RST | Reset | 若值为 1,表示 TCP 连接出现异常,必须强制断开 |
SYN | Synchronize | 用于建立连接,值为 1 表示希望建立连接 |
FIN | Fin | 该值若为 1,表示后面不再有数据包发送过来,希望断开连接 |
因此,我们可以根据控制位不同 bit 的值进行数据包过滤。但需要提醒的是,这些控制位是可以同时设定的,所以下面的示例中使用了 &
进行按位与计算:
tcp[13] & 1 == 1
捕获设置了 FIN 位的数据包;tcp[13] & 2== 2
捕获设置了 SYN 位的数据包;tcp[13] & 4 == 4
捕获设置了 RST 位的数据包;tcp[13] & 8 == 8
捕获设置了 PSH 位的数据包;tcp[13] & 16 == 16
捕获设置了 ACK 位的数据包;tcp[13] & 32 == 1
捕获设置了 URG 位的数据包;tcp[13] == 18
捕获设置了 SYN-ACK 位的数据包;- ……
防火墙中便使用了类似的规则,如果不想让局域网外的数据包进来,就可以将本机回复给局域网外的 ACK 包拦截掉,这样 TCP 三次握手失败,连接也就建立不起来了。
更多捕获过滤器的用法,请参考官方文档[5]。
数据包处理
时间格式设定
时间格式对于分析数据包来说也是非常重要的,使用绝对时间简单易懂,而使用相对时间则更能看出各个包之间的延迟。而 Wireshark 之所以强大,就在于对这些基础功能的支持。菜单栏中选择 “View - Time Display Format” 即可对时间格式进行调整,如下图所示:
默认情况下,Packet List(数据包列表)中显示的是相对于整个捕获文件的起始时间(即 “Seconds Since Begining Of Capture”),时间精度为自动(即 “Automatic (from capture file)”。但我们可以根据需要将其调整为绝对时间,比如下面选择的就是 “Date and Time of Day (1970-01-01 01:02:03:123456)” 后展示的结果:
除了上面不同的时间格式,如果想基于某个数据包看后续数据包的相对时间,可以在选中某个数据包后右击选择 “Set/Unset Time Reference”,如下图所示:
将第 6 个数据包设置相对时间参考,后续的 7-12 等几个数据包所展示的相对时间正是在第 6 个包的基础上计算出来的。
还有一个与时间相关的功能是时间偏移:即将数据包的时间戳向前或向后偏移一段时间。这个在分析不同来源的数据包时非常有用,因为不同机器上的时间可能有差距(理想情况下网络上不同设备的时间是同步的),所以通过设置偏移,即可将时间校正回来。
在菜单栏中点击 “Edit - Time Shift…” ,在弹框中按指定格式填写时间差。上图中,笔者将所有数据包都向前偏移了 1 分 2 秒 1 毫秒,所以绝对时间都向前推进了。需要说明的是,如果这里显示的是相对时间,你可能看不到变化,因为它们之间的时间差并没有变化。
保存,导出与合并
保存可以选择多种格式,而导出则可以更灵活,比如只保存选中的数据包,或一定范围的数据包等。
当对某些数据包进行标记后(右击数据包,然后“Mark/Unmark Packet”),在导出选项中就可以勾选“Market packets only”,即只导出被标记的数据包。
而合并功能则在处理多数据包时比较有用,当打开一个捕获文件后,可以通过 “File - Merge…” 来加载另一个捕获文件,默认情况下会按照时间顺序进行合并。
搜索
针对捕获好的文件,如果需要查找相关信息,直接按 ”Ctrl - F“ 会出现一个搜索框:
- Display filter:显示过滤器,比如
ip.addr == 192.168.31.50
,下文将对此进行详细介绍; - Hex value:使用输入的十六进制对数据包进行搜索,比如
01 01
; - String:直接使用字符串搜索,比如
text/html
; - Regular Expression:正则表达式,比如
Seq=3*
。
搜索时,按住 ”Ctrl - N“ 可以找到下一个满足条件的数据包,上一个则使用 ”Ctrl - B“ 。
显示过滤器
前面介绍了捕获过滤器,这里又来一个显示过滤器,二者有啥关系?
其实很简单,一个用于捕获前设置,一个用于捕获后分析。
也就是说,捕获过滤器的设置是将需要的数据包抓取下来,不需要的都扔掉。这样做,一方面是为了节约存储空间,而更重要的是去除干扰源,降本增效。因为数据越多,Wireshark 不仅抓取时要耗费大量处理器资源和网络带宽,而且后续分析起来也越慢,效率低。
而下面要介绍的显示过滤器,则是对已经捕获下来的数据包文件进行过滤分析,比如只显示当前想看的数据包,暂时隐藏其他数据包。官方针对二者的区别,也进行了说明,即 “Display filter is not a capture filter”[6]。
上一小节中,我们通过 ”Ctrl - F“ 唤出搜索框发现了其中的显示过滤器(Display filter),但这里只是搜索,而更常用的方式其实很简单:工具栏下面的 ”Apply a display filter …“。
通过显示过滤器可以快速过滤信息,比如只展示 http 协议的数据包,则输入 http
,如果不想看 udp 协议的包,则可以输入 not udp
或 !udp
。
当我们将过滤表达式内容清除以后,就又会恢复到初始状态,所以很灵活。
那么,显示过滤器的语法与前面说的 BPF 有什么区别吗?
我个人觉得差异不大,是类似的语法,其主要涉及两类操作符:
1)比较操作符
==
:等于!=
:不等于>
:大于<
:小于>=
:大于等于<=
:小于等于
2)逻辑操作符
and
:与or
:或not
:非xor
:异或(即有且仅有一个条件满足)
表达式简单来说,就是对某个(或多个)条件进行判断,比如下面的示例:
ip.addr == 192.168.31.50
:只显示与 192.168.31.50 这个 IP 地址相关的流量ip.addr == 192.168.31.50 or ip.addr == 192.168.31.22
:只显示与这两个 IP 地址相关的流量frame.len<=128
:只查看长度小于等于 128 的数据包!tcp.port == 3389
:将 tcp 协议中 3389 端口的流量过滤掉tcp.flags.rst == 1
:显示只有 RST 标志位的 TCP 数据包smtp || pop || imap
:文本 email 的流量http.response.code eq 200
:显示 http 响应码是 200 的数据包- ……
那我们记不住这么多条件怎么办?
WireShark 早已替我们想到了,菜单栏选择 ”Analyze - Display Filter Expression…“,在弹出的框中可以搜索相关条件,比如下图的 tcp:
找到对应的判断条件,比如这里的 tcp.flags.push
,然后选择操作符,比如 ==
,点击 ”OK“ 就会回到主页面中,十分方便。
另外,Wireshark 还提供了保存过滤器规则等功能,把我们日常使用的过滤规则保存下来,方便后续直接使用,如下图所示:
结合 Wireshark 的强大辅助,使用显示过滤器还是比较容易上手的,更多内容可以参考官方文档[7]。
数据包分析
前面介绍了数据包的捕获和处理,下面我们来说说数据包的分析。通过捕获的文件,结合 Wireshark ,分析网络流量的分布,调用延迟等,从中发现问题或为已知问题寻找根因。
统计
1、Endpoint
这里的端点指的是网络上可以接收或发送数据的一台设备,通过端点统计,能够查看到一些比较有用的信息,比如端点地址、接收或发送数据包的数量、字节数等。点击 “Statistics - Endpoints” :
截图的上面是默认的端点类型,我们可以通过右下角的 “Endpoint Types” 来新增或删除部分端点类型。在统计列上单击,即可按照对应列进行排序,由此便能知道哪些端点的流量高了。
2、Conversation
上面是根据节点进行统计的,但数据交换一般都需要 “客户端 - 服务端” 两个节点参与,一个负责发,一个负责收。为此,我们需要使用到 Wireshark 提供的会话统计功能。点击 “Statistics - Conversations” :
从上图可知,会话统计比端点统计更直观,我们一眼就能看到两个端点之间的流量分布。比如,192.168.31.50 是本机,它与 211.95.34.35 之间的流量字节数最多——1336 k,但包的数量却不是最多。再观察 192.168.31.50 与 112.80.248.76 之间的包,包数量有 1782 个,排名第一,如果点击 “Packets” 列,那么排名第一的就不是 211.95.34.35,而是 112.80.248.76 了。这又说明什么呢?说明与 112.80.248.76 交互的数据包平均字节数要比 211.95.34.35 小。
另外,从统计列上我们还可以看到相对启动时间(如果勾选下方的 “Absolute start time”,则会显示绝对时间),交互时长,网络速率等,这些指标对于我们分析网络问题是十分有用的。
那这些 IP 对应的域名是什么呢?因为域名更具可读性,能让我们快速了解与哪个网络交互的最频繁,流量占比最大等。对于这个问题,这里先缓一下,留到后面的 “解析” 小节中再进行阐述。
3、Protocol Hierarchy
从协议分层结构来对网络包进行统计,又能看到什么呢?点击 “Statistics - Protocol Hierarchy” :
结果也非常简单,按照 OSI 的结构,从底层开始展示其树状分支:
Frame(原始数据帧)
--- Ethernet(以太网)
--- IPv6
--- IPv4
--- UDP
--- TCP
--- TLS
--- HTTP
--- ...
--- IGMP
--- ICMP
--- ARP
是不是非常直观清晰?结合其他列展示的百分比,分析人员一眼就能看出来哪些协议的流量占比高。假设平时 ARP 流量占比不到 5%,但在最近的一次抓包中却上升到了 40%,那就说明哪里出现了问题,需要进一步深入分析。
关于统计列的含义,官方[8]也有详细说明,这里对统计列中的 “Packets” 和 ”End Packets“ 进行一个补充[9]:
Show the number of packets, and the number of bytes in those packets, for each protocol in the trace. It organizes the protocols in the same hierarchy in which they were found in the trace. Besides counting the packets in which the protocol exists, a count is also made for packets in which the protocol is the last protocol in the stack. These last-protocol counts show you how many packets (and the byte count associated with those packets) ended in a particular protocol. In the table, they are listed under “End Packets” and “End Bytes”.
这里的 End 其实指的是协议栈中最后一层(也就是最上层,后面没有协议基于它进行数据交换),即统计该协议是最后一层的包数据和字节数大小。
4、Packet Lengths
将数据包按照字节大小进行分类统计,也是我们分析网络问题的一大利器。点击 “Statistics - Packet Lengths” :
那怎么看这个统计数据呢?首先我们要对数据包的大小有一个基本认识:
- 以太网头部大小:一般为 14 字节[10]
- IP 头部大小:至少 20 字节[11]
- TCP 头部大小:至少 20 字节[12]
- UDP 头部大小:一般为 8 字节[13]
- ……
- MTU:Maximum Transmission Unit,最大传输单元,以太网一般为 1500 字节
- MSS:Maximum Segment Size,最大分段大小,
MSS = MTU - IP 头长度 - TCP 头长度
,即一个网络包所能容纳的 TCP 数据的最大长度 - ……
有了上面的基础知识,我们现在知道,如果没有数据部分,一个 TCP 包至少有 44 个字节。据此,我们可以推导出:大数据包一般表示数据传输,而小数据包则表示协议控制序列。前面抓包截图中位于 40-79 部分的数据包,基本上都是不包含数据的 TCP 控制包,比如 ACK,RST,FIN 等,而 1280 - 2559 部分则是用于数据传输的包。
解析
1、域名解析
前面在看统计数据时说到, IP 不直观,最好是能翻译成域名来分析。需要怎么做呢?
其实非常简单,点击左下角的 “Name resolution” ,但这里是灰的,无法选择。原因在于,Wireshark 默认将 IP 地址解析给关掉了,无法使用。为此,我们需要先开启,点击 “Wireshark - Preferences… - Name Resolution”,勾选 “Resolve network(IP) addresses”:
接着,再回到统计页面,就可以对 ”Name resolution“ 进行操作了:
可以看到,部分 IP 已经解析成了域名,但还有一部分可能没有域名或解析不出来[14],比如 192.168.31.50 是我本机。如果想对这些局域网的地址进行解析,可以配置 DNS Server 解析地址,或配置本地 hosts 文件。这里笔者通过配置 hosts 文件来进行域名解析:
1)在 “Wireshark - Preferences… - Name Resolution” 中,开启 “Only use the profile “hosts” file”:
2)macOS 上在 ~/.config/wireshark/hosts
中配置 IP - 域名映射关系:
➜ wireshark > ls
cfilters decode_as_entries dfilters hosts language profiles recent_common
colorfilters dfilter_buttons expert_severity io_graphs preferences recent
➜ wireshark > cat hosts
192.168.31.50 localhost-dev
➜ wireshark >
3)重新点开 “Statistics - Endpoints”,可以看到 192.168.31.50 已经被解析成了 localhost-dev:
2、协议解析
在前面一篇文章中,已经列出了 Wireshark 支持的各种协议,Wireshark 在处理数据包时会根据端口号等信息找到匹配的协议进行解析。
但 Wireshark 不是每次都能匹配正确,比如服务端使用 80 端口进行文件传输,而 Wireshark 则将其当做 http 解析肯定是有问题的。在类似情况下,就需要人工干预了。我们可以选中某个数据包,然后右击选择 ”Decode as“:
在弹出的配置框中,Wireshark 默认将其当做了 http 协议处理,如果有问题,我们可以在 ”Current“ 选项中将其调整为正确的协议。
每一类协议的解析都要对该协议有较深入的理解,比如 IP,TCP 等。如果有时间阅读 Wireshark 项目中协议解析相关的源码[15],对我们理解这些协议将会大有裨益。
3、其他名称解析
除了前面提到的域名解析,在 “Wireshark - Preferences… - Name Resolution” 下还有很多其他的名称解析选项:
Resolve MAC addresses
:使用 ARP 协议,将二层 MAC 地址解析成三层网络地址;Resolve transport names
:解析端口,将数字转换为常用的协议名称,比如将 80 解析成 http(80);Resolve network(IP) addresses
:这个前文已说明,将网络地址解析成域名;Use captured DNS packet data for address resolution
:从已捕获的 DNS 数据包中解析出 IP 地址和 DNS 域名之间的映射关系;Use an external network name resolver
:使用外部网络服务器解析域名等;Use custom list of DNS servers for name resolution
:手动配置 DNS 服务器列表,在数据中心内部非常有用;Maximum concurrent requests (default 500)
:DNS 并发请求上限,防止占用过多带宽和机器资源。- ……
上面各项的演示比较简单,笔者这里就直接略过。
需要补充的是,开启名称解析是存在弊端的。从最后一项配置的 DNS 并发请求上限可以知道,如果存在大量的名称解析,会耗费较大的机器资源,并占用网络带宽。另一方面,则是安全风险,如果数据包中有恶意 IP 地址,那么使用外部解析服务,可能会将本地的网络信息暴露出去,从而带来被黑客攻击的风险。
图形展示
除了前面提到的数据统计,还有一种方式可以查看捕获文件的网络流量统计情况,这就是图形展示,包括 IO 图、双向时间图和数据流图。前二者一般使用柱状图和折线图表示,数据流图则可以认为是时序图。下面笔者便结合下载 WPS 安装包的捕获文件,对这三种图形进行一个简单说明。
1、IO Graph
IO 图,顾名思义就是对网络吞吐量进行图形绘制,了解网络流量的分布情况,并由此找到流量的峰谷,不同协议的性能情况等。点击 ”Statistics - IO Graphs“:
从绘制的结果来看:
-
网络速率一目了然:这里 Y 轴(Y Axis)选择的是 Packets,即每秒包的数量 Packets/ 1 sec。图上数据显示每秒有 7000 左右个包,并且浮动不大,说明网络还是比较稳定的,如果将 Y 轴更新为 Bytes,我们就能看到速度了:
- 存在问题的 TCP 连接也非常直观:通过配置显示过滤器(Display Filter),来定位需要查看的流量,并使用柱状图(Style=Bar, Color=Red)来与所有的 TCP 连接(折线图,Style=Line,Color=Yellow)进行区分;
- 默认情况下,分析数据的时间间隔 Interval 为 1 秒,可以根据需要进行调整;
- 如果不同的时间段,IO 图差异大,就说明哪里出现了问题,需要进一步梳理并分析;
- ……
2、Round Trip Time Graph
IO 图用于分析网络流量的分布情况,而 RTT 图则通过分析请求延迟来寻找网络瓶颈,即通信过程中哪些调用比较慢。这里的 RTT 指的是一来一回所耗时间之和,即从发送数据包开始,到接收到对方回复包为止,这中间所耗费的时间。
点击 ”Statistics - TCP Stream Graphs - Round Trip Time“:
当笔者第一眼看到这幅图,深深地被震撼到了,真的很美。
从图上,我们可以看到网络延迟很低,大部分都在 10 ms 以下,只有极少数几个请求超过 25 ms,这就进一步验证我们的网络环境是比较不错的。如果网络存在一些问题,我们应该优先去分析那些延迟较高的数据包,从中看看能否发现一些线索。
另外,在右下方有一个 ”Switch Direction“ 按钮,这个的作用是调换方向来分析 RTT,因为 TCP 连接是双向的。
3、Flow Graph
最后一个是数据流图,笔者觉得可以将其理解为链路追踪,因为它主要的作用是将主机之间的交互,用可视化的方式呈现出来。点击 ”Statistics - Flow Graph“:
每一条竖线代表一台主机,如果与多台机器交互,那么这些箭头就会指向不同的 IP ,从而汇聚成一个时序图。有了时序图,我们对整个程序或服务的网络拓扑也就有了一个基本的全局视图,这对我们分析或理解问题是很有帮助的。
其他
最后,再简单补充两个数据包分析的功能:一个是包的状态分析,另一个是跟踪数据流。
1、专家信息
这里的专家信息,其实就相当于一个知识库,可以对数据包中出现的状态进行分析和解释。点击 ”Analyze - Expert Information“:
Wireshark 中每种协议的解析器中都有一些专家信息,主要分为四类:
1)Chat(对话)
Chat 用于表示通信中的基本信息,比如 ”TCP window update“,用来通知发送者 TCP 接收窗口的大小已被改变。
2)Note(注意)
这里指值得注意的事件,可以理解为正常通信中的异常数据包,比如 http 请求返回 404 响应码,再比如上图中的 ”Duplicate Ack“,即重复 ACK ,表示网络中有丢包的情况。
3)Warning(警告)
通信过程中收到不同寻常的错误码,比如上图中的 ”Connection reset“(即连接被重置),说明某一端的连接异常断开了,而 ”This frame is a (suspected) out-of-order segment“ 则表示数据包可能出现了乱序。
4)Error(错误)
这是最严重的级别,表示数据包中出现了严重的错误。从上面的截图中可以看到,错误的数据包有 6016 个,至于具体的错误就要根据分类逐个分析了,这里不做过多赘述。
2、流跟踪
数据通信的过程中,一般都是按照一定的顺序和规则进行交互的。如果分析时,也可以按照一定的格式将这些交互的数据包顺序展示,那处理效率将会大大提高。这就是流跟踪,它比在 ”Packet List“ 中逐个点击查看要简单高效得多。
先在 ”Packet List“ 中选中某个包,然后点击 ”Analyze - Follow - xxx Stream“(也可以对选中的包右击,然后选择 ”Follow - xxx Stream“),即可查看流:
目前支持的流包括:TCP,UDP,TLS,HTTP,HTTP/2 等。如上图所示,HTTP 协议的流跟踪可以看到对应的请求和响应信息。但如果是 TLS 这样有加密的协议,那么流跟踪的结果会是密文,无任何可读性。为此,我们需要配置对应的私钥以及密码等信息。关于这部分内容,笔者将会在后续 TLS 协议的学习笔记中进行详细阐述,这里就不做过多延伸。
总结
Wireshark 的功能非常多,笔者这里也只是根据书上的内容,并结合官方文档进行了简单的梳理。针对日常的网络问题,Wireshark 是一个利器,掌握它,将会给我们的工作带来非常大的便利。另外,笔者在学习网络相关知识时,结合 Wireshark 的抓包实战,对我理解网络协议也发挥了很大的作用。
所以,掌握 Wireshark 的基本功能,是一个程序员必备的技能。如果在分析流量时,数据量大,那么捕获/显示过滤器便能派上用场了。使用过程中,如果不清楚怎么玩,官方文档往往是最好的去处。
https://www.wireshark.org/docs/wsug_html_chunked/ChCapCaptureOptions.html ↩︎
https://www.wireshark.org/docs/wsug_html_chunked/ChCapCaptureFilterSection.html ↩︎
https://wiki.wireshark.org/CaptureFilters#capture-filter-is-not-a-display-filter ↩︎
https://www.wireshark.org/docs/wsug_html_chunked/ChStatHierarchy.html ↩︎
https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure ↩︎
https://en.wikipedia.org/wiki/User_Datagram_Protocol#UDP_datagram_structure ↩︎
解析失败的,也可以使用 whatismyip ( https://www.whatismyip.com/ip-address-lookup/ ) 之类的网络进行手动处理。 ↩︎
每个协议的解析代码在 https://gitlab.com/wireshark/wireshark/-/tree/master/epan/dissectors 下 packet-<协议名称>.c 的文件中。 ↩︎