Wireshark文档 | Wireshark 过滤器

Wireshark 和 TShark 共享一个强大的过滤引擎,有助于消除数据包跟踪中的噪音,让您只看到您感兴趣的数据包。如果数据包满足过滤器中表达的要求,则它会显示在数据包列表中。显示过滤器让您可以将协议中的字段与特定值进行比较,将字段与字段进行比较,并检查指定的字段或协议是否存在。

检查字段或协议是否存在

最简单的过滤器允许您检查协议或字段是否存在。如果您想查看所有包含 IP 协议的数据包,过滤器将是ip。要查看包含令牌环 RIF 字段的所有数据包,请使用tr.rif

将过滤器中的协议或字段视为隐式具有“存在”运算符。

比较运算符

字段也可以与值进行比较。比较运算符可以通过类似英文的缩写或类似 C 语言的符号表示:

1
2
3
4
5
6
7
8
运算符     描述
———————————————————————————————————————————
eq, ==    (等于)Equal
ne, !=    (不等于)Not Equal
gt, >     (大于)Greater Than
lt, <     (小于)Less Than
ge, >=    (大于等于)Greater than or Equal to
le, <=    (小于等于)Less than or Equal to

搜索和匹配操作符

其他运算符仅以英语表达,而不是类似 C 语言的语法:

1
2
3
4
5
运算符        描述
———————————————————————————————————————————
contains     协议、字段或切片是否包含值
matches, ~   协议或文本字符串是否与给定匹配
             不区分大小写的perl兼容正则表达式

“contains” 运算符允许过滤器搜索一系列字符,表示为字符串(带引号或不带引号),或字节,表示为字节数组,或单个字符,表示为 C 语言样式字符常量。例如,要在捕获中搜索给定的 HTTP URL,可以使用以下过滤器:

1
http contains "https://www.google.com"

“contains” 运算符不能用于原子字段,例如数字或 IP 地址。

“matches” 或 “~” 运算符允许过滤器应用于指定的 Perl 兼容正则表达式 (PCRE)。 “matches” 操作符仅用于协议和具有文本字符串表示的协议字段。默认情况下,匹配不区分大小写。例如,要搜索给定的 HTTP Chrome User-Agent,您可以编写:

1
http.user_agent matches "chrome"

这将匹配“chrome”、“CHROME”、“ChRome”或任何其他大小写字母组合。当然,您可以使用强制区分大小写

1
http.user_agent matches "(?-i)chrome"

这是 PCRE (?option) 结构的一个示例。 (?-i) 执行区分大小写的模式匹配,但也可以指定其他选项。更多信息可以在 https://perldoc.perl.org/perlre.html 的 pcrepattern(3) 手册页中找到。

功能

过滤语言有以下功能:

1
2
3
4
5
upper(string-field) - 将字符串字段转换为大写
lower(string-field) - 将字符串字段转换为小写
len(field)          - 返回字符串或bytes字段的字节长度
count(field)        - 返回帧中出现的字段数
string(field)       - 将非字符串字段转换为字符串

upper() 和 lower() 可用于执行不区分大小写的字符串比较。例如:

1
2
upper(http.user_agent) matches "CHROME"
lower(mysql.user) == "root"

string()将字段值转换为字符串,适合与“matches”或“contains”等操作符一起使用。整数字段被转换为十进制表示。它可以用于IP/以太网地址(以及其他地址),但不能用于字符串或字节字段。例如:

1
string(frame.number) matches "[13579]$"

展示出所有frame为奇数的数据包。

协议字段类型

每个协议字段都被输入。类型是

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
ASN.1 object identifier
Boolean
Character string
Compiled Perl-Compatible Regular Expression (GRegex) object
Date and time
Ethernet or other MAC address
EUI64 address
Floating point (double-precision)
Floating point (single-precision)
Frame number
Globally Unique Identifier
IPv4 address
IPv6 address
IPX network number
Label
Protocol
Sequence of bytes
Signed integer, 1, 2, 3, 4, or 8 bytes
Time offset
Unsigned integer, 1, 2, 3, 4, or 8 bytes
1-byte ASCII character

整数可以用十进制、八进制或十六进制表示法表示,或者表示为 C 语言风格的字符常量。以下六个显示过滤器是等效的:

1
2
3
4
5
6
frame.pkt_len > 10
frame.pkt_len > 012
frame.pkt_len > 0xa
frame.pkt_len > '\n'
frame.pkt_len > '\xa'
frame.pkt_len > '\012'

布尔值是真或假。在测试布尔字段值的显示过滤器表达式中,“真”表示为 1 或任何其他非零值,“假”表示为 0。例如,令牌环数据包的源路由字段是布尔值。要查找任何源路由数据包,显示过滤器将是:

1
tr.sr == 1

可以通过以下方式找到非源路由数据包:

1
tr.sr == 0

以太网地址和字节数组由十六进制数字表示。十六进制数字可以用冒号、句点或连字符分隔:

1
2
3
4
eth.dst eq ff:ff:ff:ff:ff:ff
aim.data == 0.1.0.d
fddi.src == aa-aa-aa-aa-aa-aa
echo.data == 7a

IPv4 地址可以用点分十进制表示:

1
2
ip.src == 192.168.0.105
ip.dst == 39.156.69.79

IPv4 地址可以用与数字相同的逻辑关系进行比较:eq、ne、gt、ge、lt 和 le。 IPv4 地址按主机顺序存储,因此在显示过滤器中使用 IPv4 地址时不必担心 IPv4 地址的字节序。

无类别域间路由 (CIDR) 表示法可用于测试 IPv4 地址是否在某个子网中。例如,此显示过滤器将查找 129.111 B 类网络中的所有数据包:

1
ip.addr == 192.168.0.0/16

IPX 网络由无符号 32 位整数表示。在测试 IPX 网络值时,您很可能会使用十六进制:

1
ipx.src.net == 0xc0a82c00

字符串用双引号括起来:

1
http.request.method == "POST"

在双引号内,您可以使用反斜杠嵌入双引号或以八进制或十六进制表示的任意字节。

1
browser.comment == "An embedded \" double-quote"

使用十六进制查找“HEAD”:

1
http.request.method == "\x48EAD"

使用八进制查找“HEAD”:

1
http.request.method == "\110EAD"

这意味着您必须使用双引号内的反斜杠来转义反斜杠。

1
smb.path contains "\\\\SERVER\\SHARE"

在“smb.path”中查找 \SERVER\SHARE。

切片操作

如果字段是文本字符串或字节数组,则您可以对字段进行切片。例如,您可以过滤以太网地址的供应商部分(前三个字节),如下所示:

1
eth.src[0:3] == 00:00:83

另一个例子是:

1
http.content_type[0:4] == "text"

您也可以在协议名称上使用切片运算符。 “frame”协议可能很有用,它包含 WiresharkTShark 捕获的所有数据。

1
2
3
token[0:5] ne 0.0.0.1.1
llc[0] eq aa
frame[100-199] contains "wireshark"

以下语法管理切片:

1
2
3
4
5
[i:j]    i = start_offset, j = length
[i-j]    i = start_offset, j = end_offset, inclusive.
[i]      i = start_offset, length = 1
[:j]     start_offset = 0, length = j
[i:]     start_offset = i, end_offset = end_of_field

偏移量可以是负数,在这种情况下,它们表示距字段末尾的偏移量。该字段的最后一个字节在偏移量 -1 处,最后一个字节在偏移量 -2 处,依此类推。以下是检查帧的最后四个字节的方法:

1
2
3
frame[-4:4] == 0.1.2.3
# or
frame[-4:] == 0.1.2.3

切片总是与字符串或字节序列进行比较。作为一种特殊情况,当切片只有 1 个字节宽时,您可以将其与 0xff 或更小的十六进制整数进行比较(这意味着它适合一个字节)。这对于大于一个字节的字节序列是不允许的,因为这样就需要指定多字节整数的字节序。此外,这对于十进制数是不允许的,因为它们会与已经允许作为字节字符串的十六进制数混淆。然而,单字节十六进制整数可能很方便:

1
frame[4] == 0xff

切片可以组合。您可以使用逗号运算符连接它们:

1
ftp[1,3-5,9:] == 01:03:04:05:09:0a:0b

这将偏移量 1、偏移量 3-5 和偏移量 9 连接到 ftp 数据的末尾。

集合操作

只需使用成员组运算符,就可以检查字段是否与一组值匹配。例如,您可以使用以下过滤器查找常见 HTTP/HTTPS 端口上的流量:

1
tcp.port in {80 443 8080}

以上操作等价于:

1
tcp.port == 80 or tcp.port == 443 or tcp.port == 8080

要使用 HEAD 或 GET 方法查找 HTTP 请求:

1
http.request.method in {"HEAD" "GET"}

这组值还可以包含范围:

1
2
3
tcp.port in {443 4430..4434}
ip.addr in {10.0.0.5 .. 10.0.0.9 192.168.1.1..192.168.1.9}
frame.time_delta in {10 .. 10.5}

类型转换

如果字段是文本字符串或字节数组,则可以用最方便的方式表示。

因此,例如,以下过滤器是等效的:

1
2
http.request.method == "GET"
http.request.method == 47.45.54

范围也可以用任何一种方式表示:

1
2
frame[60:2] gt 50.51
frame[60:2] gt "PQ"

位域操作

也可以使用位域操作来定义测试。目前支持以下位域操作:

1
bitwise_and, &      Bitwise AND

按位与操作允许测试以查看是否设置了一位或多位。按位 AND 对整数协议字段和切片进行操作。

在测试 TCP SYN 数据包时,您可以编写:

1
tcp.flags & 0x02

该表达式将匹配所有包含“tcp.flags”字段且设置了 0x02 位(即 SYN 位)的数据包。

同样,通过以下方式过滤所有 WSP GET 和扩展 GET 方法:

1
wsp.pdu_type & 0x40

使用切片时,位掩码必须指定为字节字符串,并且必须与切片本身具有相同的字节数,如下所示:

1
ip[42:2] & 40:ff

逻辑表达式

可以使用逻辑表达式组合测试。这些也可以用类似 C 语言的语法或类似英语的缩写来表达:

1
2
3
4
5
运算符     描述
———————————————————————————————————————————
and, &&   逻辑与
or,  ||   逻辑或
not, !    逻辑非

表达式也可以按括号分组。以下是所有有效的显示过滤器表达式:

1
2
3
4
tcp.port == 80 and ip.src == 192.168.2.1
not llc
http and frame[100-199] contains "wireshark"
(ipx.src.net == 0xbad && ipx.src.node == 0.0.0.0.0.1) || ip

请记住,只要表达式中出现协议或字段名称,就会隐式调用“exists”运算符。 “exists”运算符具有最高优先级。这意味着第一个过滤器表达式必须读作“向我显示 tcp.port 存在且等于 80 且 ip.src 存在且等于 192.168.2.1 的数据包”。第二个过滤器表达式的意思是“向我显示不存在(llc 存在)的数据包”,或者换句话说“在 llc 不存在的地方”,因此将匹配所有不包含 llc 协议的数据包。第三个过滤器表达式包括帧中存在偏移199的约束,即帧的长度至少为200。

对于每个数据包出现多次的字段,必须特别注意。 “ip.addr”在每个 IP 数据包中出现两次,一次用于源地址,一次用于目标地址。同样,“tr.rif.ring”字段可以在每个数据包中出现多次。以下两个表达式不等价:

1
2
    ip.addr ne 192.168.4.1
not ip.addr eq 192.168.4.1

第一个过滤器说“向我显示存在不等于 192.168.4.1 的 ip.addr 的数据包”。也就是说,只要数据包中的一个ip.addr不等于192.168.4.1,数据包就通过了显示过滤器。另一个 ip.addr 可能等于 192.168.4.1 并且数据包仍会显示。第二个过滤器说“不要向我显示任何具有等于 192.168.4.1 的 ip.addr 字段的数据包”。如果一个ip.addr是192.168.4.1,则数据包不通过。如果 ip.addr 字段都不是 192.168.4.1,则显示数据包。

在处理多次重复字段时,很容易将 ’ne’ 和 ’eq’ 运算符视为具有隐式 “exists” 修饰符。 “ip.addr ne 192.168.4.1” 可以认为是 “存在一个不等于192.168.4.1的ip.addr”。 “not ip.addr eq 192.168.4.1”可以认为是“不存在等于192.168.4.1的ip.addr”。

小心重复出现的字段;他们可能会令人困惑。

使用显示过滤器从数据包跟踪中去除噪声时也必须小心。例如,如果您想过滤掉所有地址为 224.1.2.3 的 IP 多播数据包,则使用:

1
ip.dst ne 224.1.2.3

可能太严格了。使用“ip.dst”过滤只会选择那些满足规则的 IP 数据包。不会显示任何其他数据包,包括所有非 IP 数据包。要同时显示非 IP 数据包,您可以使用以下两个表达式之一:

1
2
not ip or ip.dst ne 224.1.2.3
not ip.addr eq 224.1.2.3

第一个过滤器使用“not ip”来包含所有非 IP 数据包,然后让“ip.dst ne 224.1.2.3”过滤掉不需要的 IP 数据包。上面已经解释了第二个过滤器,其中讨论了使用多个出现的字段进行过滤。

特定使用场景

针对IP地址过滤

IP地址过滤可以通过 ip.addr 进行过滤,也可以通过 ip.dst 和 ip.src 进行过滤,它们之间有些区别,下面具体来看。

ip.addr 进行过滤时,源和目标IP地址只要包含时,都会被展示,具体使用方式如下

1
2
# ip.addr eq 10.10.10.183
ip.addr == 10.10.10.183

ip.dst 进行过滤时,只展示目标IP地址匹配的数据包列表

1
2
# ip.dst eq 10.10.10.183
ip.dst == 10.10.10.183

ip.src 进行过滤时,只展示源IP地址匹配的数据包列表

1
2
# ip.src eq 10.10.10.183
ip.src == 10.10.10.183

针对端口过滤

针对端口过滤数据包,这个需要根据具体的传输协议及端口来过滤数据包。

通过如下的方式,过滤TCP协议433端口数据包

1
tcp.port == 433

通过如下的方式,过滤UDP协议9408端口数据包

1
udp.port == 9408

通过如下的方式,过滤DNS协议数据包

1
dns

针对长度和内容过滤

1
udp.lenght < 30

针对数据包内容过滤

针对HTTP请求方法类型过滤

下面这条表达式意为,过滤HTTP请求类型是POST,并且目标IP地址是118.186.60.194的数据包。

1
http.request.method == "POST" && ip.dst == 118.186.60.194

相关参考

显示过滤器的整个列表太大,无法在此处列出。您可以在以下位置找到参考资料和示例:

comments powered by Disqus