自己写了一个WinPcap过滤表达式语法检测软件,使用了SharpPcap包(它是使用.net对WinPcap进行了封装,其中过滤表达式和WinPcap相同)。
程序下载地址为:http://download.csdn.net/source/526497
源代码下载地址为:http://download.csdn.net/source/526501
转了两篇文章,第一篇写的很短但是很清楚,第二篇写的比较长,但是很详细。
转自:http://hi.baidu.com/jsjzpt/blog/item/aac60e9b984c53b1c8eaf40a.html
在捕获网络数据时,常常只需捕获某些特定的数据,因此在编写sniffer类的软件时,需要加入数据过滤的功能。Winpcap是sniffer软件最常用的开发库之一,在Winpcap中通过编辑过滤表达式来设置过滤条件。下面就以Winpcap开发库为例,介绍数据过滤功能的实现。
Winpcap过滤表达式采用tcpdump的语法,是一个ASCII字符串形式的高层的布尔表达式。表达式由用户(或程序员)编辑,由pcap_compile()编译成内核级的代码,编译后pcap_setfilter()将其应用到某个已打开的网络捕获设备(网卡)上。每一个来自网络的数据包都会被检查,所有的符合要求的数据包(即与过滤条件比较后,布尔表达式为真的包)将会被Winpcap堆存。
一个数据包的关键属性包括协议(如IP)、发送和接收方(如源和目的IP地址)等,这些信息都可以在PDU头部找到。Winpcap通过读取PDU头部相应字段,并结合过滤条件完成过滤操作。
过滤表达式的基本组成元素为关键词,一个表达式由一个或多个关键词组成,关键词之间通过and、or和not连接。关键词主要有两类:
第一类 声明数据包源或目的地的关键词。关键词host、net和port分别指明依据收、发方IP地址(或主机名)、网络地址和端口号进行判断,若未指定,则默认为host;关键词前加上修饰词dst、src 和dst or src 指明捕获特定方向的数据,若未指定,则默认为dst or src。
如“dst host 210.31.234.254”,“port 80”,“src 210.31.234.13”。
第二类 声明数据包协议类型的关键词。关键词ether、fddi、tr、ip、ip6、arp、rarp、tcp和udp分别指明数据链路层、网络层和传输层所用协议类型。
IP分组类型的ip proto等。如“ether proto /arp”、“ip proto /tcp”。
转自:http://blog.csdn.net/casale/archive/2006/05/29/760421.aspx 作者:陈伯仁
注:该文档从tcpdump的主页上获得,在www.tcpdump.org能够找到它的原始版本。
Wpcap过滤器基于已公开的断言语法。一个过滤器是一串包括过滤表达式的ASCII字符串。Pcap_compile()接受表达式并利用一个程序将之转化为核心层的包过滤器。
表达式选择将要接受的数据包。若未给出表达式,网络上的所有数据包将被核心层的过滤驱动所接受。否则,只有满足表达式为”ture”的数据包会被接受。
表达式可以包括一个或多个原子式。原子式通常由一个带前置限定词的id(名称或数字)所组成。有三种不同的前置限定词:
Type 限定词指定名称或数字所指向的类别。可能的类别有host、net和port。例如:’host foo’、’net 128.3’、’port 20’。若未指定类别限定词,默认为host。
Dir 限定词指定一个到和/或从id的特定的传输方向。可能的方向有src、dst、src or dst和src and dst。例如:’src foo’、’dst net 128.3’、’src or dst port ftp-data’。若没有该限定词,默认为src or dst。对于’null’链路层(例如像slip这种点对点的协议)inbound和outbound这两上限定词能够指定想要的方向。
Proto 限定词限定一个特殊的协议。可能的协议有:ether、fddi、tr、ip、ip6、arp、rarp、decnet、tcp和udp。例如:’ether src foo’、’arp net 128.3’、’tcp port 21’。若没有协议限定词,则默认为所有与类别相一致的协议。例如:’src foo’的意思是’(ip or arp or rarp) src foo’(除非后面的语法不合法),’net bar’的意思是’(ip or arp or rarp) net bar’,’port 53’的意思’(tcp or udp) port 53’。
[‘fddi’实际上是’ether’的一个别名;解析器将它们的意思处理为“在指定网络接口下使用数据链路层。”FDDI首部包括类以太网的源和目的地址,并且通常包括类以太网的包类型,因此你能够像对以太网一样在这些部分对FDDI进行过滤。FDDI首部还包括其他部分,但你无法在过滤表达式中精确命名它们。
类似的,’tr’是’ether’的一个别名;之前对FDDI首部的解释也适用于令牌环网的首部。]
做为对以上的补充,还有一些特殊的‘原子式’的关键字并不遵循这种模式:gateway、broadcast、less、greater和算术表达式。所有这些将在后面讲到。
更复杂的过滤表达式由and、or和not将原子式组合而成。例如:’host foo and not port ftp and not port ftp-data’。简略起见,样同的限定试列表可以省略。例如:’tcp dst port ftp or ftp-data or domain’与’tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'完全一样。
合法的原子式有:
dst host host
如果IPv4/v6数据包的目的地址是host则表达式值为true,host可以是IP地址或主机名。
src host host
如果IPv4/v6数据包的源地址是host则表达式值为true。
host host
如果IPv4/v6数据包的源或目的地址是host则表达式值为true。以上的任一主机表达式都能够用关键字如ip、arp、rarp或ip6预先指定,就像以下所示:
Ip host host
等价于:
Ether proto /ip and host host
如果host是多个IP地址,每个地址都会被做匹配检查。
ether dst ehost
若以太网目的地址是ehost则值为true。ehost可以是/etc/ethers中的一个名称或一个数字(请见ethers(3N)的数字格式)。
ether src ehost
若以太网源地址是ehost则值为true。
ether host ehost
若以太网源或目的地址是ehost则值为true。
gateway host
若数据包以host为网关则值为true。例如:以太网的源或目的地址是host但无论是IP地址的源还是目的地址都不是host。Host必须是一个名称并且能够在机器的host-name-to-IP-address机制(如主机名文件、DNS、NIS)和host-name-to-Ethernet-address机制(如/ect/ethers)中找到。(一个等价的表达式是:
ether host ehost and not host host
它能够使用名称或数字表示host / ehost 。)目前来说,这种语法无法在能够运行IPv6的结构下工作。
dst net net
若IPv4/v6的目的地址的网络号是net,则值为true。Net可以是/etc/networks中的一个名称或是一个网络号(详细内容请见networks(4))。
src net net
若IPv4/v6的源地址的网络号是net,则值为true。
net net
若IPv4/v6的源地址或目的地址的网络号是net,则值为true。
net net mask netmask
若IP地址根据指定的子网掩码netmask能与net匹配。可以用限定词src或dst限定。注意:这个语法在IPv6中是不合法的。
net net/len
若IPv4/v6地址根据指定的子网掩码长度能与net匹配。可以用限定词src或dst限定。
dst port port
若数据包是ip/tcp、ip/udp、ip6/tcp或ip6/udp并且目的端口为port,则值为true。端口可以是一个数字或一个在/etc/services(详见tcp(4P)和udp(4P))中的名称。若使用名称,则端口和协议都将被指定。若使用数字或不明确的名称,则只有端口地址被指定(例如:dst port 513将显示tcp/login和udp/who的数据流,port domain将显示tcp/domain和udp/domain的数据流)。
src port port
若数据包的源端口的值是port,则值为true。
port port
若数据包的源或目的端口地址的值是port,则值为true。以上所有关于端口的表达式都可以用关键字,tcp或udp,预先指定,如:
tcp src port port
仅当tcp的数据包的源端口地址为port的时才匹配。
less length
若数据包的长度小于等于length,则值为true。这相当于:
len <= length。
greater length
若数据包的长度大于等于length,则值为true。这相当于:
len >= length。
ip proto protocol
若数据包是协议类型为protocol的IP数据包(详见ip(4P))。Protocol可以是一个数字或一个名称:icmp 、icmp6 、igmp 、igrp 、pim 、ah 、esp 、vrrp 、udp或tcp。注意标识符tcp 、udp 、和icmp同时又是关键字并且必需经过反斜线(/)过滤(在C-shell中是//)。注意这个原子式不对协议首部进行分析。(这段话理解不太清楚,原文如下:Note that the identifiers tcp, udp, and icmp are also keywords and must be escaped via backslash (/), which is // in the C-shell. Note that this primitive does not chase the protocol header chain.)
ip6 proto protocol
若数据包是协议类型为protocol的IPv6数据包。注意这个原子式不对协议首部进行分析。
ip6 protochain protocol
若数据包是IPv6数据包,并且在它的协议首部串中包括类型为protocol的协议首部,则值为ture。例如:
ip6 protochain 6
与任何在协议首部串中包括TCP协议首部的IPv6数据包匹配。数据包可能包括,例如:在IPv6首部和TCP首部之间包括authentication首部,routing首部或hop-by-hop option首部。由该原子式发送的BPF编码是很复杂的并且在tcpdump中不能被BPF编码优化器所优化,因此它可能有点慢。
ip protochain protocol
等价于ip6 protochain protocol,但是它用于IPv4。
ether broadcast
若数据包是以太网广播数据包,则值为true。关键字ether是可选的。
ip broadcast
若数据包是IP广播数据包,则值为true。它会检察所有全一和全零的广播协定并查寻本地子网掩码。
ether multicast
若数据包是以太网多播数据包,则值为true。Ether关键字是可选的。这是‘ether[0] & 1 != 0’的简写。
ip multicast
若数据包是IP多播数据包,则值为true。
ip6 multicast
若数据包是IPv6多播数据包,则值为true。
ether proto protocol
若数据包是protocol类型的以太协议,则值为true。Protocol可以是一个数字或以下中的一个名称:ip 、 ip6 、 arp 、 rarp 、 atalk 、 decnet 、 sca 、 lat 、 mopdl 、 moprc 、 iso 、 stp 、 ipx或netbeui。注意这些标识符同时也是关键字并且必须用反斜线(/)过滤。
[在FDDI(如‘fddi protocol arp’)和令牌环(如‘tr protocol arp’)的例子中,对于大多数的协议来说,协议证明来自802.2的逻辑链接控制(LLC)首部,LLC通常在首部分层中处于FDDI或令牌环的顶层。
当过滤FDDI或令牌环网络的大部分协议时,对于压缩以太网tcpdump只检查在所谓的SNAP格式的组织单元标识符(OUI)值为0x000000的LLC首部的协议的ID字段;它并不检查数据包是否在SNAP格式下拥有OUI值为0x000000。例外的是iso,它检查的是LLC首部的DSAP(Destination Service Access Point)和SSAP(Source Service Access Point)字段;stp和netbeui检查LLC首部的DSAP;还有atalk检查拥有OUI为0x080007的SNAP格式数据包和Appletalk etype(这个怎么译)。
在以太网的例子中,tcpdump检查大部分协议的以太网类型字段;例外的是iso、sap和netbeui,对于这些它检查802.3的帧,然后像它对FDDI和令牌环网做的那样检查LLC首部;atalk,它检查以太网帧中的Appletalk etype并且同时像在FDDI和令牌环网中那样检查SNAP格式的数据包;aarp,它在以太网帧或OUI值为0x000000的802.2 SNAP帧中检查Appletalk ARP etype;还有ipx,它检查以太网帧中的IPX etype,LLC首部的IPX DSAP,没有LLC首部封装的802.3的IPX和SNAP帧中的IPX etype。]
decnet src host
若DECNET的源地址是host,则值为true,它可能是一个格式为‘10.123’的地址或一个DECNET的主机名称。[DECNET主机名称支持只有在配置成运行DECNET的Ultrix系统中可用。]
decnet dst host
若DECNET目的地址为host,则值为true。
decnet host host
若DECNET的源或目的地址为host,则值为true。
ip 、 ip6 、 arp 、 rarp 、 atalk 、 decnet 、 iso 、 stp 、 ipx 、 netbeui
缩写为:
ether proto p
P是以上协议中的一个。
lat 、 moprc 、 mopdl
缩写为:
ether proto p
p是以上协议中的一个。注意tcpdump目前还不知道如何解析这些协议。
vlan [vlan_id]
若数据包是IEEE 802.1Q VLAN数据包,则值为true。若[vlan_id]被指定,则仅当数据包为指定的vlan_id,值才为true。注意在表达式中遇到的第一个关键字vlan在假设数据包为VLAN数据包的前提下改变了剩下的表达式的解码偏移量。
tcp 、 udp 、 icmp
缩写为:
ip proto p or io6 proto p
p是以上协议中的一个。
iso proto protocol
若数据包是协议类型为protocol的OSI数据包,则值为true。Protocol可以是一个数字或以下名称中的一个:clnp 、 esis或isis。
clnp 、 esis 、 isis
缩写为:
iso proto p
p是以上协议中的一个。注意tcpdump在解析这些协议时所做的工作并不完全。
expr relop expr
若关系式如下:relop是 >、<、>=、<=、=、!= 中的一个,并且expr是一个由正整常数(用标准C的语法表达)、标准二进制操作[+、-、*、/、&、| ]和指定数据包存取,则值为true。要存取数据包内的数据,可以使用以下的语法:
proto [ expr : size ]
proto 是ether 、 fddi 、 tr 、 ip 、 arp 、 rarp 、 tcp 、 udp 、 icmp或ip6同的一个,并且用索引操场作指定协议层。注意tcp 、 udp和其他上层协议类型仅应用于IPv4,而不能应用于IPv6(这在将来将会改进)。相对于指定的协议层,字节偏移量是由expr给出。Size是可选的,它指定感兴趣的字段的字节数;它可以是1、2或4,默认为1。由len指定的长度操作会给出数据包的长度。
例如:‘ether[0] & 1 != 0’捕获所有多播的数据流。表达式‘ip[0] & 0xf != 5’捕获所有选中的IP数据包。表达式‘ip[6:2] & 0x1fff = 0’仅捕获不分片的数据和分片数据的第0片数据。这些检查将暗中的应用于tcp和udp的索引操作。例如:tcp[0]总是意味着TCP首部的第一个字节,而决不会意味着一个中间片段的第一个字节。
某些偏移量和字段值可能是用名称来表达而不是数值。以下的协议首部字段偏移量可用:icmptype (ICMP类型字段)、icmpcode (ICMP代码字段)和tcpflags (TCP标识字段)。
以下的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。
以下的TCP标识字段值可用:tcp-fin、tcp-syn、tcp-rst、tcp-push、tcp-push、tcp-ack、tcp-urg。
原子式可以使用以下操作进行组合:
一个加上括号的原子式和操作的组(圆括号专用于Shell因此必须过滤掉)。
否(‘!’或‘not’)。
与(‘&&’或‘and’)。
或(‘||’或‘or’)。
否具有最高的优先级。与和或具有相同的优先级且是左连接的。注意外在的and记号不是并列的,而是要求串联的。
如果一个标识符给出时没有关联关键字,则假设为最近使用过的关键字。例如:
not host vs and ace
是以下表达式的简写:
not host vs and host ace
不要与以下的表达式混淆了:
not ( host vs or ace )
表达式参数可以以单个参数的形式也可以以多个参数的形式传给tcpdump。一般的,若表达式包括Shell metacharacters,传送单个引用参数更为容易。多个参数在解析前可用空格联接起来。