工作是「开心」重要还是「钱」重要
前言
Wireshark 提供了一种显示过滤语言,可以精确控制显示哪些报文。它们可用于检查协议或字段的存在,字段的值,甚至比较两个字段。这些比较可以与逻辑操作符(如“and”和“or”)以及圆括号组合成复杂的表达式。
我们可以根据实际需求进行选择和运用,以实现更加精确的过滤功能。譬如,如果只显示 IP 192.168.0.1 的报文,则使用:
ip.addr == 192.168.0.1
显示过滤比较运算符
以下显示了 Wireshark 显示过滤中可以使用的比较运算符的完整列表。
English |
Alias |
C-like |
Description |
Example |
eq |
any_eq |
== |
Equal (any if more than one) |
ip.src == 10.0.0.5 |
ne |
all_ne |
!= |
Not equal (all if more than one) |
ip.src != 10.0.0.5 |
all_eq |
=== |
Equal (all if more than one) |
ip.src === 10.0.0.5 |
|
any_ne |
!== |
Not equal (any if more than one) |
ip.src !== 10.0.0.5 |
|
gt |
> |
Greater than |
frame.len > 10 |
|
lt |
< |
Less than |
frame.len < 128 |
|
ge |
>= |
Greater than or equal to |
frame.len ge 0x100 |
|
le |
<= |
Less than or equal to |
frame.len <= 0x20 |
|
contains |
Protocol, field or slice contains a value |
sip.To contains "a1762" |
||
matches |
~ |
Protocol or text field matches a Perl-compatible regular expression |
http.host matches "acme\.(org|com|net)" |
English 和 C-like 运算符是可互换的,可以在显示过滤表达式字符串中混合使用。
显示过滤字段类型
-
Unsigned integer
可以是 8, 16, 24, 32, 和 64 位,可以用十进制、八进制、十六进制或二进制表示。下面的显示过滤表达式是等效的:
ip.len le 1500
ip.len le 02734
ip.len le 0x5dc
ip.len le 0b10111011100
-
Signed integer
可以是 8, 16, 24, 32, 和 64 位,同样可以使用十进制、八进制、十六进制或二进制。
-
Boolean
可以是 1 或 "True", 0 或 "False"。
-
Ethernet address
6 字节,由冒号 (:)、点 (.) 或破折号 (-) 分隔,分隔符之间为 1 或 2 个字节。
eth.dst == ff:ff:ff:ff:ff:ff
eth.dst == ff-ff-ff-ff-ff-ff
eth.dst == ffff.ffff.ffff
-
IPv4 address
ip.addr == 192.168.0.1
ip.addr == 129.111.0.0/16
-
IPv6 address
ipv6.addr == ::1
-
Text string
http.request.uri == "https://www.wireshark.org/"
dns.qry.name contains "www.x77x69x72x65x73x68x61x72x6b.org"
http.user_agent matches r"(X11;"
-
Date and time
frame.time == "Sep 26, 2004 23:18:04.954975"
ntp.xmt ge "2020-07-04 12:34:56"
frame.time < "2022-01-01"
显示过滤示例
下面将举例几种比较常用的显示过滤表达式。
-
is present
首先介绍一个很特殊的运算符,表示 "存在",用于匹配包含此字段的任意包,譬如过滤 TCP 或者 HTTP 数据包,表达式如下:
tcp
或
http
原始数据包
过滤 TCP 数据包
过滤 HTTP 数据包
当然,既然是 "存在" 的含义,表达式 ip.addr
或 tcp.flags.syn
也会过滤成功。
通过简单几个例子,你是否有明白 "is present" 的含义。
-
==
"==" 等于运算符,与特定值进行比较,表示严格匹配。这个在显示过滤中经常使用,像是开篇提到的表达式 ip.addr == 192.168.0.1
。
还有一层含义是 "any_eq",也就是 "Equal (any if more than one)",表示如果有多个相同字段,任一字段的值能严格匹配上即满足。
原始数据包
过滤 IP 地址等于 192.168.0.2 的数据包
当然使用 "eq" 是同样的结果
在一个数据包中,如果通过 ip.addr
过滤,实际上会有两个字段可以匹配,一个是源 IP,一个是目的 IP,对于 "=="运算符,只要任意一个匹配上即满足。
譬如通过 ip.addr == 192.168.0.1
可以过滤出源或者目的 IP 值为 192.168.0.1 的数据包。
-
!=
"!=" 不等于运算符,与特定值进行比较,表示不匹配。
还有一层含义是 "all_ne",也就是 "Not equal (all if more than one)",表示如果有多个相同字段,所有字段的值均不匹配才满足,注意这里指的是过滤出来的数据包,不是指的过滤掉的数据包。
原始数据包
过滤源 IP 地址不为 192.168.0.1 的数据包
使用 "ne" 是同样的结果
当然加上逻辑运算符 not 也可以得到同样的结果
English 和 C-like 运算符混合使用的结果
甚至于混合使用的一个反例,也是可以成功的。
对于 "all_ne",也就是 "Not equal (all if more than one)",譬如通过 ip.addr != 192.168.0.1
过滤出源和目的 IP 都不是 192.168.0.1 的数据包,全都满足,即 all 。
-
===
相较于 "==" 运算符,"===" 运算符的匹配更加严格,需要全部匹配上才满足,即 "all_eq",也就是 "Equal (all if more than one)" 的含义。
也就是说在一个数据包中,如果通过 ip.addr === 192.168.0.1
需要过滤出源和目的 IP 均为 192.168.0.1 的数据包。
原始数据包
过滤出源和目的 IP 地址全部等于 192.168.0.1 的数据包。
-
!==
相较于 "!=" 运算符,"!==" 运算符的匹配反而宽松,任一字段值不匹配即满足,即 "any_ne",也就是 "Not Equal (any if more than one)" 的含义。
也就是说在一个数据包中,如果通过 ip.addr !== 192.168.0.1
会过滤出源或目的 IP 的值任一不为 192.168.0.1 的数据包。
原始数据包
过滤出源或目的 IP 的值任一不为 192.168.0.1 的数据包,即 any,而过滤掉的是源和目的 IP 值均为 192.168.0.1 的数据包。
-
>
表示大于。
原始数据包
过滤 tcp.len > 100
表示仅过滤出 TCP 包长度大于 100 的数据包。
-
<
表示小于。
原始数据包
过滤 tcp.len < 100
表示仅过滤出 TCP 包长度小于 100 的数据包。
-
>=
表示大于等于。
原始数据包
过滤 frame.len >= 191
表示仅过滤出数据帧长度大于等于 191 的数据包。
-
<=
表示小于等于。
原始数据包
过滤 frame.len <= 66
表示仅过滤出数据帧长度小于等于 66 的数据包。
10. contains
协议、字段或切片中包含一个值。
过滤 tcp contains d2:09:00:50
表示仅过滤出 Source Port: 53769 和 Destination Port: 80 的数据包。
11. matches
协议或文本字段匹配 perl 兼容的正则表达式。
过滤 Http 请求 URI 中匹配 "/api/heartbeat.json" 的数据包。
过滤 Http 请求 URI 中匹配 "register" 或 "heartbeat" 或 "task" 或 "result".json 的数据包。
总结
总之,Wireshark 是一种非常强大的网络分析工具,如果能够熟练掌握其中的过滤字段和运算符的用法,将可以极大地提高分析数据包的效率和准确性。
往期推荐
原文始发于微信公众号(Echo Reply):Wireshark 提示和技巧 | 显示过滤中的比较值
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论