设置过滤规则就是让网络设备只是捕获我们感兴趣的网络数据包,如果没有设置过滤规则,即上面的 filter_app 是空字符串,那么网络设备就捕获所有类型的数据包,否则只是捕获过滤规则设置的数据包,此时过滤规则的逻辑值为真。此过滤规则是通用的,由著名的网络程序 tcpdump 推出,其他很多的网络程序都是基于此规则进行设计的。此过滤规则的内部解析机制上面介绍过,下面我们参考 tcpdump 的过滤规则形式着重介绍一下过滤规则的定义形式。
///*过滤长度小于500的数据包
sudo tcpdump -d greater 500
(000) ld #pktlen
(001) jge #0x1f4 jt 2 jf 3
(002) ret #262144
(003) ret #0
//sudo tcpdump -dd greater 500
struct sock_filter BPF_code[] = {
{0x80, 0, 0, 0x00000000},
{0x35, 0, 1, 0x000001f4},
{0x6, 0, 0, 0x00040000},
{0x6, 0, 0, 0x00000000}};
struct sock_fprog Filter;
Filter.len = 4;
Filter.filter = BPF_code;
struct ifreq req;
strcpy(req.ifr_name, wlan);
ioctl(sock, SIOCGIFINDEX, &req);
///* Attach the filter to the socket */
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
&Filter, sizeof(Filter)) < 0)
{
perror("setsockopt");
close(sock);
exit(1);
}
过滤规则由一个或多个原语组成。原语通常由一个标识(id, 名称或数字)和标识前面的一个或多个限定词组成。
过滤规则有三种类型的限定词,分别为 type、dir 和 proto。
1.type
类型限定词,说明标识的类型,即名字的类型或数字的类型。大概有 host、net 和 port 三种类型。例如 ’host foo’, ’net 128.3’, ’port 20’。如果不指定类型修饰字,就使用默认的 host。
2.dir
方向限定词,说明相对于标识的传输方向,即数据是传入还是传出标识。可以使用的方向有 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 限定词指定所需的传输方向。
3.proto
协议限定词,说明过滤规则指定的协议。可以使用的协议有: ether, fddi, ip, arp, rarp, decnet,lat, sca, moprc, mopdl, tcp 和 udp。例如,’ether src foo’, ’arp net 128.3’, ’tcp port 21’。如果不指定协议限定词,就使用所有符合类型的协议。例如,’src foo’ 指(ip 或 arp 或 rarp)src foo’ , ’netbar’ 指 ’ (ip 或 arp 或 rarp) net bar’, ’port 53’ 指(tcp 或 udp)port 53’。
更复杂的过滤器表达式可以通过 and(&&), or(||) 和 not(!) 连接原语来组建。例如,’host foo and notport ftp and not port ftp-data’。为了简便,可以忽略相同的限定词。例如,’tcp dst port ftp orftp-data or domain’ 实际上等价于 ’tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain’。
下面介绍过滤规则的原语,允许的原语有以下几种。
dst host host1
如果报文中 IP 的目的地址域是 host1,则逻辑为真。host1 既可以是地址,也可以是主机名。此过滤规则就是捕获所有目的地址是 host1 的网络数据包。
src host host1
如果报文中 IP 的源地址域是 host1,则逻辑为真。即捕获所有源地址是 host1 的所有网络数据包。
host host1
如果报文中 IP 的源地址或者目的地址是 host1,则逻辑为真。即捕获所有源地址或者目的地址是 host1 的网络数据包。
上面所有的 host 表达式都可以加上 ip, arp 或 rarp 关键字做前缀,就像:
ip host host1
它等价于:
ether proto \ip and host host1
如果 host1 是拥有多个 IP 地址的主机名, 它的每个地址都会被查验。
ether dst ehost
如果报文的以太目的地址是 ehost,则逻辑为真。即捕获所有以太网目的地址是 ehost 的网络数据包。其中 ehost 既可以是名字,如 eth0 (/etc/ethers 里有),也可以是数字。
ether src ehost
如果报文的以太网源地址是 ehost,则逻辑为真。即捕获所有以太网源地址是 ehost 的网络数据包。
ether host ehost
如果报文的以太源地址或以太目的地址是 ehost,则逻辑为真。即捕获所有以太网源地址或者目的地址是 ehost 的网络数据包。
gateway host
如果报文把 host 当做网关,则逻辑为真。也就是说,报文的以太网源或目的地址是 host,但是 IP 的源目地址都不是 host。此 host 必须是个主机名,而且必须存在于/etc/hosts 和/etc/ethers 中。一个等价的表达式是:
ether host ehost and not host host1
对于 host1 和 ehost,它既可以是名字,也可以是数字。
dst net net1
如果报文的 IP 目的地址属于网络号 net1,则逻辑为真。net1 既可以是名字(存在/etc/networks 中),也可以是网络号。即捕获所有目的地址属于网络 net1 的网络数据包。
src net net1
如果报文的 IP 源地址属于网络号 net1,则逻辑为真。即捕获所有源地址属于网络 net1的网络数据包。
net net1
如果报文的 IP 源地址或目的地址属于网络号 net1,则过滤规则逻辑为真。即捕获所有源地址或者目的地址属于网络 net1 的网络数据包。
net net1 mask mask1
如果 IP 地址匹配指定网络掩码 mask1 的 net1,则逻辑为真。本原语可以用 src 或 dst 修饰。
net net1/len
如果 IP 地址匹配指定网络掩码的 net1,则逻辑为真,掩码的有效位宽为 len。本原语可以用 src 或 dst 修饰。
dst port port1
如果报文是 ip/tcp 或 ip/udp,并且目的端口是 port1,则逻辑为真。port1 是一个数字,也可以是/etc/services 中定义过的名字。如果使用名字,则检查端口号和协议。如果使用数字,或者有二义的名字,则只检查端口号。例如,dst port 513 将显示 tcp/login 的数据和 udp/who的数据,而 port domain 将显示 tcp/domain 和 udp/domain 的数据。
src port port1
如果报文的源端口号是 port1,则逻辑为真。即捕获所有源端口号是 port1 的网络数据包。
port port
如果报文的源端口或目的端口是 port,则逻辑为真,上述的任意一个端口表达式都可以用关键字 tcp 或 udp 做前缀,就如:
tcp src port port1
它只匹配源端口是 port1 的 TCP 报文。即捕获所有源端口号是 port1 的协议是 tcp 的网络数据包。
less length
如果报文的长度小于等于 length,则逻辑为真。即只捕获所有长度小于 length 的网络数据包。它等同于:len <= length.
greater length
如果报文的长度大于等于 length,则逻辑为真。即只捕获所有长度大于 length 的网络数据包。它等同于:len >= length.
ip proto protocol
如果报文是 IP 数据报,其内容的协议类型是 protocol,则逻辑为真。即只捕获网络协议类型是 protocol 的 ip 数据包。protocol 可以是数字,也可以是下列名称中的一个:icmp, igrp,udp, nd 或 tcp。注意这些标识符 tcp, udp 和 icmp 也同样是关键字,所以必须用反斜杠(\)义,在 C-shell 中应该是\\。
ether broadcast
如果报文是以太广播报文,则逻辑为真。即捕获以太网广播数据包。关键字 ether 是可选的。
ip broadcast
如果报文是 IP 广播报文,则逻辑为真。检查全 0 和全 1 的广播约定,并且检查本地的子网掩码。
ether multicast
如果报文是以太多目传送报文(multicast),则过滤规则逻辑为真。关键字 ether 是可选的。这实际上是 ’ether[0] & 1 != 0’ 的简写。
ip multicast
如果报文是 IP 多目传送报文,则过滤规则逻辑为真。即捕获 ip 多目传送报文。
ether proto protocol
如果报文协议属于以太类型的 protocol,则逻辑为真。Protocol 可以是数字,也可以是名字,如 ip, arp 或 rarp。注意这些标识符也是关键字,所以必须用反斜杠(\)转义。如果是 FDDI(例如,’fddi protocol arp’),协议标识来自 802.2 逻辑链路控制(LLC)报头,它通常位于FDDI 报头的顶层。当根据协议标识过滤报文时,那么就假设所有的 FDDI 报文含有 LLC 报头,而且 LLC 报头用的是 SNAP 格式。
decnet src host
如果 DECNET 的源地址是 host,则逻辑为真,该主机地址的形式可能是’’10.123’’,或者是 DECNET 主机名。只有配置成运行 DECNET 的 Ultrix 系统支持 DECNET 主机名。
decnet dst host
如果 DECNET 的目的地址是 host,则逻辑为真。
decnet host host
如果 DECNET 的源地址或目的地址是 host,则逻辑为真。
ip, arp, rarp, decnet是 ether proto p 的简写形式,其中 p 为上述协议的一种。
tcp, udp, icmp是 ip proto p 的简写形式,其中 p 为上述协议的一种。
expr relop expr
如果这个关系成立,则逻辑为真,其中 relop 是 >, <, >=, <=, =, != 之一, expr 是数学表达式,由常整数(标准 C 语法形式),普通的二进制数运算符[+, -, *, /, &, |],一个长度运算符,和指定的报文数据访问算符组成。要访问报文内的数据,使用下面的语法:
proto [ expr : size ]
proto 是 ether, fddi, ip, arp, rarp, tcp, udp, or icmp 之一,同时也指出了下标操作的协议层。
expr 给出字节单位的偏移量,该偏移量相对于指定的协议层。Size 是可选项,指出感兴趣的字节数;它可以是 1, 2, 4, 默认为 1 字节。由关键字 len 给出的长度运算符指明报文的长度。
字节数;它可以是 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 报头的第一个字节,而不是其中某个 IP 片的第一个字节。
原语可以用下述方法结合使用:
圆括弧括起来的原语和操作符。取反操作 (’!’ or ’not’),联结操作 (’&&’ or ’and’) 或操作(’||’ or ’or’)。取反操作有最高优先级。或操作和联结操作有相同的优先级,运算时从左到右结合。注意联结操作需要显式的 and 算符,而不是并列放置。
如果给出标识符,但没给关键字,那么暗指最近使用的关键字。例如,not host vs and ace
作为 not host vs and host ace 的简写形式,不应该和 not ( host vs or ace )混淆。表达式参数可以作为单个参数传给捕获程序,也可以作为复合参数,后者更方便一些。
引用自: