Wireshark 基础 | 捕获过滤篇
Wireshark 基础系列 | 捕获过滤篇
目录
简介
「Wireshark 捕获过滤」(capture filter),一句话解释就是抓包过滤,需要抓取哪些特定的数据包。
作用
简单来说的原因就是性能,如果明确知道需要或不需要分析某个协议类型的流量,那么就可以使用捕获过滤器进行过滤,从而节省处理器资源。因此当网卡传输大量数据流量的时候,通过捕获过滤器进行过滤是很有用处的。
但如果性能满足或者你对协议交互流量不那么清楚的情况下,建议还是抓全包,原因是很有可能过滤掉某些有用的数据包,会导致无法分析到产生问题的真正原因。
语言
Wireshark 捕获过滤器是用 libpcap 过滤语言所编写。该语法概述可见官方 User’s Guide,完整文档可详见:pcap-filter man page 。
Wireshark 捕获过滤器与 tcpdump、WinDump、Analyzer 等使用 libpcap/WinPcap 库的任何其他程序使用相同的语法。
建议
学习直接从 Tcpdump Man page of PCAP-FILTER 入手即可,详见 pcap-filter man page 。
语法
捕获过滤器表达式
[not] primitive [and|or [not] primitive ...]
过滤器表达式由一个或多个 原语 组成,原语 通常由一个 id (名称或数字)和一个或多个 限定符 组成。
限定符
三种类型限定符,包括 type (类型)、dir (方向)、proto (协议) 。
type (类型)
host, net, port 和 portrange
默认 host
dir (方向)
src, dst, src or dst, src and dst
默认 src or dst
proto (协议)
ether, ip, ip6, arp, tcp 和 udp
默认和 type 一致的所有协议
特殊原语关键字
gateway, broadcast, less, greater 和算术表达式等。
[x] , x 为可选
x|y , 选 x 或 y
<x> , x 为必选
xyz , xyz 为关键字,必需
and(&&)、or(||)、not(!), 代表与、或、非
二层过滤
ehost
格式
ether [src|dst] host <ehost>
示例
ether host <ehost>、
ether src <ehost>、ether src host <ehost>
ether dst <ehost>、ether dst host <ehost>
mac 地址支持多种写法:“xx:xx:xx:xx:xx:xx”, “xx.xx.xx.xx.xx.xx”, “xx-xx-xx-xx-xx-xx”, “xxxx.xxxx.xxxx”, “xxxxxxxxxxxx”
broadcast|multicast
格式
[ether] broadcast|multicast
示例
broadcast、multicast、
ether broadcast、ether multicast
IPv4 多播流量,其目的 MAC 地址必以 01:00:5e 开头;
IPv6 多播流量,其目的 MAC 地址必以 33:33 开头。
vlan
格式
vlan <vlan>
示例
vlan <vlan>
vlan <vlan 1> and vlan <vlan 2>
vlan and vlan <vlan 1>
- vlan 编号;
- vlan 表达式可以使用不止一次,以过滤 vlan 层次结构,每次使用该表达式都会使过滤器偏移量增加 4 ;
- vlan2 封装在 vlan1 中;
- vlan1 封装在任意 vlan 中。
len
格式
less|greater <length>
示例
less <length>、greater <length>
- frame 长度;
- 等同于 len <= length、len >= length 。
三层过滤
host
格式
[ip|ip6|arp|rarp] [src|dst] host <host>
示例
host <host>、src host <host>、dst host <host>、
ip host <host>、ip src host <host>、
arp host <host>、arp dst host <host>
...
net
格式
[src|dst] net <net> [{mask <mask>}|{/<len>}]
示例
net <net>、src net <net>、dst net <net>、
net <net> mask <mask>、src net <net> mask <mask>、
net <net>/<len>、net <net> /<len>
...
broadcast|multicast
格式 & 示例
ip broadcast|multicast
ip6 multicast
gateway
格式
gateway <host>
匹配以太网地址是 host ,但 IP 地址不是 host 的数据包
等同于 ether host <ehost> and not host <host>
示例
gateway test
- host 必须为 名字 ;
- 必须同时在 主机名-IP地址 (host name file, DNS 等) 和 主机名-以太网地址( /etc/ethers 等)文件中找到相对应的解析;
- Tcpdump 支持,但很少用( wireshark 不支持)。
四层过滤
port
格式
[tcp|udp] [src|dst] port|portrange <port>
示例
port <port>、src port <port>、dst port <port>、
portrange <port1-port2>、src portrange <port1-port2>、dst portrange <port1-port2>、
tcp port <port>、tcp dst port <port>、
tcp portrange <port1-port2>、tcp dst portrange <port1-port2>
...
协议过滤
ether
格式
ether proto <proto>
或
ip|ip6|arp
可以是 数字(以太网协议编号 ,包括 IP 0x0800、IPv6 0x86dd、ARP 0x0806 等),也可以是 名字(包括 ip、ip6、arp、rarp、stp 等),名字需加 转义符 \,譬如 ether proto \ip 。
ip|ip6
格式
[ip|ip6] proto <proto>
[ip|ip6] protochain <proto>
或
tcp|udp|icmp|icmp6
示例
proto <proto>、ip proto <proto>、ip6 proto <proto>
...
- 可以是 数字(包括1、6、17等),也可以是 名字(包括 icmp, icmp6, igmp, igrp, pim, ah, esp, vrrp, udp, 或 tcp),名字需加 转义符 \,譬如 ip proto \tcp;
- wireshark 下 protochain 与 proto 使用基本无区别;在 tcpdump 下区别在于输出显示,protochain 会把数据包中协议头链中所有协议头内容打印显示出来。
mpls
格式
mpls [label_num]
示例
mpls、mpls [label_num]、
mpls [label_num1] and mpls [label_num2]、
mpls and mpls [label_num]
...
- mpls 标签号;
- mpls 表达式可以使用不止一次,以过滤 mpls 层次结构,每次使用该表达式都会使过滤器偏移量增加 4 ;
- 内部标签 num2,外部标签 num1;
- 内部标签 num 封装在任意外部标签中。
复合型过滤
与、或、非
格式
and、or、not
或
&&、||、!
示例
tcp port <port> and host <host>、
ip && host <>、
tcp port <port> or udp port <port>、
host <host> || host <host>、
not arp and host <host>、
! tcp and port <port>
...
特殊过滤
语法
<expr> relop <expr>
-
relop :>,<,>=,<=,=,!=
-
expr :一个算术表达式,由整型常量、二进制运算符[+、-、*、/、%、&、|、^、<<、>>]、长度运算符和特定数据包数据引用运算符组成。
- &(and) 两者都为 1 则为 1 ,否则为 0 ;
- |(or) 两者都为 0 为 0 ,否则为 1 。
- proto [ expr : size ]
- proto:ether, wlan, ppp, ip, arp, rarp, tcp, udp, icmp, ip6,指明该引用操作所对应的协议。
- expr:给出指定协议层的字节偏移量。
- size:可选,表示感兴趣字段中的字节数;它可以是 1、2 或 4 ,默认值是 1 。
- 长度运算符 (关键字 len 表示) 给出数据包的长度。
ether
ether[0]
Destination 目的 mac(字节偏移量 0,长度 6 字节)
示例
ether[0] & 1 != 0 所有组播广播流量,第一个字节最低位为 1,反之 = 0 ,所有单播流量
ether[4:2] = 0x12ab 过滤目的 mac 后两位字节为 12ab 的数据包
字节偏移量 0,意味着 size 1、2 或 4,选择范围均为目的 mac(6字节)内。
ether[6]
Source 源 mac(字节偏移量 6 ,长度 6 字节)
示例
ether[10:2] = 0x34cd 过滤源 mac 后两位字节为 34cd 的数据包
字节偏移量 6,意味着 size 1、2 或 4,选择范围均为源 mac(6字节)内。
ether[12]
Type(字节偏移量 12,长度 2 字节)
示例
ether[12:2] = 0x0800 IPv4 数据包
ether[12:2] = 0x0806 ARP 数据包
等同于 ip|arp
len
frame长度
示例
len <= 60 长度小于等于 60 的 frame
len >= 1500 长度大于等于 1500 的 frame
等同于 less|greater
arp
arp[0]
Hardware type(字节偏移量 0 ,长度 2 字节)
示例
arp[0:2] = 1 Ethernet
arp[2]
Protocol type(字节偏移量 2 ,长度 2 字节)
示例
arp[2:2] = 0x0800 IPv4
arp[4]
Hardware address length(字节偏移量 4 ,长度 1 字节)
示例
arp[4] = 6 硬件地址长度 6
arp[5]
Protocol address length(字节偏移量 5 ,长度 1 字节)
示例
arp[5] = 4 协议地址长度 4
arp[6]
Opcode(字节偏移量 6 ,长度 2 字节)
示例
arp[6:2] = 1 request
arp[6:2] = 2 reply
arp[8]
Source hardware address(字节偏移量 8 ,长度 n bytes,n 值为 Hardware address length)
示例
arp[12:2] = 0xb192 源 mac 地址后两位字节为 b192 的数据包
- 可变长度
- n=6,则为 6 bytes(48 bit),即源 mac 地址
arp[8+n]
Source protocol address(字节偏移量 8+n,长度 m bytes,m 值为 Protocol address length)
示例
arp[14:4] = 0x0a000001 源IP为 10.0.0.1 的 ARP 数据包
- 可变长度
- m=4,则为 4 bytes(32 bit),即源 IP 地址
arp[8+n+m]
Destination hardware address(字节偏移量 8+n+m,长度 n bytes,n 值为 Hardware address length)
示例
arp[22:2] = 0xb192 目的 mac 地址后两位字节为 b192 的数据包
- 可变长度
- n=6,则为 6 bytes(48 bit),即目的 mac 地址
- arp request 中目的 MAC 地址为全 0
arp[8+2n+m]
Destination protocol address(字节偏移量 8+2n+m,长度 m bytes,m 值为 Protocol address length)
示例
arp[24:4] = 0xac100001 目的IP为 172.16.0.1 的 ARP 数据包
- 可变长度
- m=4,则为 4 bytes(32 bit),即目的 IP 地址
ip
ip[0]
version(4bit)+ Header Length(4bit)(字节偏移量 0 ,长度 1 字节)
示例
ip[0] & 0x40 = 0x40 ip[0] & 64 = 64 ip[0] & 0xf0 = 64 IPv4 数据包
ip[0] & 0xf = 5 ip[0] & 5 = 5 IPv4 数据包首部长度 20 字节,即不含有可选字段最小值为 5,最大值为 15 number * 32-bit
ip[0] & 0xf != 5 IPv4 数据包首部中含有可选字段
ip[1]
Differentiated Services Field:Differentiated Services Codepoint(6bit)+ Explicit Congestion Notification(2bit)(字节偏移量 1 ,长度 1 字节)
ip[2]
Total Length(字节偏移量 2 ,长度 2 字节)
示例
ip[2:2] = 60 ip[2:2] >=1000 IP 数据包总长度
ip[4]
Identification(字节偏移量 4 ,长度 2 字节)
示例
ip[4:2] = 0x0
ip[6]
Flags(3bit) + Fragment offset(13bit)(字节偏移量 6 ,长度 2 字节)
示例
ip[6] & 0x4f = 0x40 ip[6:2] & 0x4fff = 0x4000 Don't fragment 位设置为 1 的 IPv4 数据包
ip[6:2] & 0x3fff = 0 没被分片的 IPv4 数据包
ip[6:2] & 0x3fff = 0x2000 分片编号为 0 的被分片的 IPv4 数据包
ip[6:2] & 0x1fff = 0 没被分片的 IPv4 的数据包或者分片编号为 0 的被分片的 IPv4 数据包
ip[6] & 0x60 = 0 and ip[6:2] & 0x1fff != 0 最后一个分片的 IPv4 数据包
ip[8]
TTL(Time to live,8bit)(字节偏移量 8 ,长度 1 字节)
示例
ip[8] = 0x80 TTL 128
ip[9]
Protocol(8bit)(字节偏移量 9 ,长度 1 字节)
示例
ip[9] = 6 TCP
ip[9] = 17 ip[9] = 0x11 UDP
ip[10]
Header checksum(16bit)(字节偏移量 10 ,长度 2 字节)
示例
ip[10:2] = 0x0000
- 首部检验和字段是根据 IP 首部计算的检验和码,它不对首部后面的数据进行计算;
- 首部中每 16 bit 进行二进制反码求和。
ip[12]
Source 源IP地址(32bit)(字节偏移量 12 ,长度 4 字节)
示例
ip[12:4] = 0x0a000001 源 IP 为 10.0.0.1 的 IPv4 数据包
ip[16]
Destination 目的IP地址(32bit)(字节偏移量 12 ,长度 4 字节)
示例
ip[16:4] = 0xac100001 目的 IP 为 172.16.0.1 的 IPv4 数据包
ip[16] >= 224 组播广播数据包
ip[20]
- Options,可变长度
- Padding,可变长度
- 0-40 字节
icmp
icmp[0]
Type(8bit)(字节偏移量 0 ,长度 1 字节)
示例
icmp[0] = 8 Echo(ping)request
icmp[0] = 0 Echo(ping)reply
icmp[1]
Code(8bit)(字节偏移量 1 ,长度 1 字节)
示例
icmp[0] = 0
icmp[2]
Checksum(16bit)(字节偏移量 2 ,长度 2 字节)
示例
icmp[2:2] = 0x4cf4
ICMP 校验和覆盖整个报文( ICMP 报头 + ICMP 数据)
icmp[4]
Identifier(BE)(字节偏移量 4 ,长度 2 字节)
Identifier(LE)(字节偏移量 4 ,长度 2 字节)
icmp[6]
Sequence number(BE)(字节偏移量 6,长度 2 字节)
Sequence number(LE)(字节偏移量 6,长度 2 字节)
icmp[8]
Data(n bytes)
Windows 默认 32 字节,填充 16 进制数据为 61626364…( ASCII 码与 16 进制转换,61 为 a,62 为 b 等等)
icmptype (icmp 类型字段)
icmp[icmptype] == <identifier>
示例
icmp[icmptype] == 0 icmp echo-reply 数据包
icmp[icmptype] == 8 icmp echo-request 数据包
icmp[icmptype] == icmp-echoreply icmp echo-reply 数据包
icmp[icmptype] == icmp-echo icmp echo-request 数据包
ICMP 类型字段值:icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect, icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob, icmp-tstamp,icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq, icmp-maskreply。
icmpcode (icmp 代码字段)
icmp[icmpcode] == <identifier>
示例
icmp[icmpcode] = 0
icmp6type (icmpv6 类型字段)
icmp6code (icmpv6 代码字段)
tcp
tcp[0]
Source Port(16bit)(字节偏移量 0 ,长度 2 字节)
示例
tcp[0:2] = 0xc871
等同于 tcp src port
tcp[2]
Destination Port(16bit)(字节偏移量 2 ,长度 2 字节)
示例
tcp[2:2] = 80
等同于 tcp dst port
tcp[4]
Sequence number(32bit)(字节偏移量 4 ,长度 4 字节)
示例
tcp[4:4] = 0x88cf222a
此段中第一个数据字节的序列号
tcp[8]
Acknowledgment number(32bit)(字节偏移量 8 ,长度 4 字节)
示例
tcp[8:4] = 0x424ade50
一旦连接建立,则总是发送。
tcp[12]
Data Offset(4bit)(字节偏移量 12 ,长度 4 bit),即 Header Length
示例
tcp[12] & 0xf0 = 80 TCP 头部长度 20 字节
number * 32-bit
tcp[13]
Reserved(3bit),必须为 0;
ECN(Explicit Congestion Notification,3bit),包括 Nonce、Congestion Window Reduced(CWR)、ECN-Echo 各 1bit;
Control Bits(6bit),包括 Urgent、Acknowledgment、Push、Reset、Syn、Fin 各 1bit。
示例
tcp[13] & 32 != 0、tcp[13] & 32 = 32 URG
tcp[13] & 16 != 0、tcp[13] & 16 = 16 ACK
tcp[13] & 8 != 0、tcp[13] & 8 = 8 PSH
tcp[13] & 4 != 0、tcp[13] & 4 = 4 RST
tcp[13] & 2 != 0、tcp[13] & 2 = 2 SYN
tcp[13] & 1 != 0、tcp[13] & 1 = 1 FIN
匹配的标志位有值设置(1),其他标志位不确定。譬如 tcp[13] & 2 != 0 抓取的有 SYN ,也有 SYN+ACK
tcp[13] = 32 URG
tcp[13] = 16 ACK
tcp[13] = 8 PSH
tcp[13] = 4 RST
tcp[13] = 2 SYN
tcp[13] = 1 FIN
匹配的标志位有值设置(1),其他标志位没有设置。譬如 tcp[13] = 2 只匹配 SYN
tcp[13] & 17 = 17 FIN+ACK 同时置 1,其他不确定
tcp[13] & 17 = 16 FIN 置 0,ACK 置 1,其他不确定
tcp[13] & 1|16 = 17 FIN 置 1,其他不确定,一般实际抓包 ACK 也置 1
tcp[13] & 16|1 = 17 ACK 置 1,其他不确定
tcp[13] & (1|16) = 17 FIN+ACK 同时置 1,其他不确定
tcp[13] & (16|1) = 17 FIN+ACK 同时置 1,其他不确定
tcp[13] & (1|16) = 1|16 FIN+ACK 同时置 1,其他不确定
tcp[13] & (1|16) = 16 FIN 置 0,ACK 置 1,其他不确定
tcp[13] = 17 FIN+ACK 同时置 1,其他无设置
tcp[13] = 1|16 FIN+ACK 同时置 1,其他无设置
&(and) 两者都为 1 则为 1,否则为 0
|(or) 两者都为 0 为 0 ,否则为 1
tcp[14]
Window size value(16bit)(字节偏移量 14 ,长度 2 字节)
示例
tcp[14:2] = 0x0200
tcp[16]
Checksum(16bit)(字节偏移量 16 ,长度 2 字节)
示例
tcp[16:2] = 0x2020
TCP伪首部
- 伪首部共有 12 字节,包含 IP 首部的一些字段,有如下信息:32 位源 IP 地址、32 位目的 IP 地址、8 位保留字节(置 0 )、8 位 IP 协议号( TCP 是 6 )、16 位报文总长度(首部+数据)。
- 伪首部是为了增加校验和的检错能力:通过伪首部的目的IP地址来检查 TCP 报文是否收错了、通过伪首部的 IP 协议号来检查传输层协议是否选对了。
- TCP 首部校验和计算三部分:TCP 首部+ TCP 数据+ TCP 伪首部;
- 如果总长度为奇数个字节,则在最后增添一个位都为 0 的字节;
- TCP 的检验和是必需的。
tcp[18]
Urgent Pointer(16bit)(字节偏移量 18 ,长度 2 字节)
示例
tcp[18:2] = 0
tcp[20]
Options,0 到 40 字节
data
可变长度
tcpflags(tcp 标记字段)
TCP 标记字段值:tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg
示例
tcp[tcpflags] & tcp-urg != 0、tcp[tcpflags] & tcp-urg = tcp-urg
tcp[tcpflags] & tcp-ack != 0、tcp[tcpflags] & tcp-ack = tcp-ack
tcp[tcpflags] & tcp-push != 0、tcp[tcpflags] & tcp-push = tcp-push
tcp[tcpflags] & tcp-rst != 0、tcp[tcpflags] & tcp-rst = tcp-rst
tcp[tcpflags] & tcp-syn != 0、tcp[tcpflags] & tcp-syn = tcp-syn
tcp[tcpflags] & tcp-fin != 0、tcp[tcpflags] & tcp-fin = tcp-fin
tcp[tcpflags] = tcp-urg
tcp[tcpflags] = tcp-ack
tcp[tcpflags] = tcp-push
tcp[tcpflags] = tcp-rst
tcp[tcpflags] = tcp-syn
tcp[tcpflags] = tcp-fin
tcp[tcpflags] & (tcp-rst|tcp-ack) = (tcp-rst|tcp-ack)
tcp[tcpflags] & (tcp-syn|tcp-ack) = (tcp-syn|tcp-ack)
udp
udp[0]
Source Port(16bit)(字节偏移量 0 ,长度 2 字节)
示例
udp[0:2] = 0x104c
等同于 udp src port
udp[2]
Destination Port(16bit)(字节偏移量 2 ,长度 2 字节)
示例
udp[2:2] = 0x6722
等同于 udp dst port
udp[4]
Length(16bit)(字节偏移量 4 ,长度 2 字节)
示例
udp[4:2] = 0x00cc
udp[6]
Checksum(16bit)(字节偏移量 6 ,长度 2 字节)
示例
udp[6:2] = 0x459e
UDP伪首部
- 伪首部共有 12 字节,包含IP首部的一些字段,有如下信息:32 位源 IP 地址、32 位目的 IP 地址、8 位保留字节(置 0 )、8 位 IP 协议号( UDP 是 17 )、16 位报文总长度(首部+数据)。
- 伪首部是为了增加校验和的检错能力:通过伪首部的目的IP地址来检查 UDP 报文是否收错了、通过伪首部的 IP 协议号来检查传输层协议是否选对了。
- UDP 首部校验和计算三部分:UDP 首部+ UDP 数据+ UDP 伪首部;
- 如果总长度为奇数个字节,则在最后增添一个位都为 0 的字节;
- UDP 的检验和是可选的。
udp[8]
Data,可变长度
实例
- 包含有 DATA 的 IPv4 数据包
ip[2:2] - ((ip[0]&0xf)<<2) - ((tcp[12]&0xf0)>>2) != 0
IPv4 数据包总长度 - IPv4 数据包首部长度 - TCP 数据包首部长度 != 0,意味着 IPv4 数据包含有 DATA
- TCP 端口范围在 1501-1540 的数据包
(tcp[0:2] > 1500 and tcp[0:2] < 1550) or (tcp[2:2] > 1500 and tcp[2:2] < 1550)
tcp portrange 1501-1549
- Welchia worm
icmp[icmptype] == icmp-echo and ip[2:2] == 92 and icmp[8:4] == 0xAAAAAAAA
- HTTP GET requests 数据包
port 80 and tcp[((tcp[12] & 0xf0) >> 2):4] = 0x47455420
'G', 'E', 'T', ' ' (16 进制值分别对应为 47, 45, 54, 20;tcp[12] & 0xf0) >> 2 为数据偏移位,取 4 字节即为 GET 。
0x504f5354 POST
- Heartbleed Exploit 数据包
tcp src port 443 and (tcp[((tcp[12] & 0xF0) >> 4 ) * 4] = 0x18) and (tcp[((tcp[12] & 0xF0) >> 4 ) * 4 + 1] = 0x03) and (tcp[((tcp[12] & 0xF0) >> 4 ) * 4 + 2] < 0x04) and ((ip[2:2] - 4 * (ip[0] & 0x0F) - 4 * ((tcp[12] & 0xF0) >> 4) > 69))
tcp[((tcp[12] & 0xF0) >> 4 ) * 4] = 0x18 和 tcp[((tcp[12] & 0xF0) >> 4 ) * 4 + 1] = 0x03 TCP 数据偏移位,可简写为 tcp[((tcp[12] & 0xf0) >> 2):2] = 0x1803,18 为 heartbeat 报文,03 为 TLS 主版本号;
tcp[((tcp[12] & 0xF0) >> 4 ) * 4 + 2] < 0x04,TLS 子版本号,等同于 tcp[((tcp[12] & 0xf0) >> 2) + 2] < 0x04;
ip[2:2] - 4 * (ip[0] & 0x0F) - 4 * ((tcp[12] & 0xF0) >> 4) > 69,TCP 数据包负载大于 69 字节,等同于ip[2:2] - ((ip[0]&0xf)<<2) - ((tcp[12]&0xf0)>>2) > 69。
感谢阅读,更多技术文章可关注个人公众号:Echo Reply ,谢谢。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)