网络包过滤语法。tcpdump的expression。

描述

pcap_compile()是用来编译一个字符串到过滤程序的函数。这导致过滤程序可以决定哪些包可以提供给pcap_loop(), pcap_dispatch(), pcap_next(), pcap_next_ex()

过滤表达式由一个或者更多的原语组成。原语由一个id(名字或者编号)组成,id可以有一个或者多个修饰符。 一共有三种不同的修饰符:

  • 类型 修饰符表示id是什么类型的。可能的类型有host, net, port, portrange。 例如,host foo, net 128.3, port 20, portrange 6000-6008。如果没有类型修饰符, 则假设是host
  • 方向 修饰符指定了流的方向是到达id或者从id出发。可能的方向有src, dst, src or dst, src and dst, ra, ta, addr1, addr2, addr3, addr4。 例如,src foo, dst net 128.3, src or dst port ftp-data。如果没有方向修饰符, 则假设是src or dstra, ta, addr1, addr2, addr3, addr4修饰符符只有对IEEE 802.11 Wireless LAN link layers有效。对于一些链路层,例如SLIP和cooked使用any捕捉任意设备或者其他的设备类型, inboundoutbound修饰符可以指定希望的方向。
  • 协议 修饰符限定了匹配的特殊协议。可能的协议有:ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp, udp。例如,ether src foo, arp net 128.3, tcp port 21, udp portrange 7000-7009, wlan addr2 0:2:3:4:5:6。如果没有指定协议修饰符, 则使用所有合法的组合。例如,src foo意味着(ip or arp or rarp) src foonet bar意味着(ip or arp or rarp) net barport 53意味着(tcp or udp) port 53

[fddi实际上是ether的别名。解析器相同的对待它们。FDDI头包含Ethernet-like源和目标地址, 经常也包含Ethernet-like包类型。所以你可以使用类型于Ethernet的域来过滤FDDI域。 FDDH头还包含其他的头,但是你不能明确地在过滤表达式中指定。

类似的,trwlanether的别名。上一节关于FDDI头的说明同样可以用于令牌环形网络和802.11 wireless LAN头。 对于802.11头,目标地址在DA域,源地址在SA域。]

除了上述之外,还有一些原始的关键字不使用以上的模式: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 domaintcp dst port ftp or tcp dst port ftp-data or tcp dst port domain是完全一样的。

合法的原语

dst host <host>

如果包的IPv4/v6目标域是<host>,可能是地址或者名字,则为true。

src host <host>

如果包的IPv4/v6源域是<host>则为true。

host <host>

如果包的IPv4/v6的源或者目标是<host>则为true。

以上任意的主机表达式可以在前面加上ip, arp, rarp, ip6的关键字。例如:

1
ip host <host>

等同于

1
ether proto \ip and host <host>

如果<host>包含多个IP地址,每个地址都会检查匹配。

ether dst <ehost>

如果Ethernet目标地址是<ehost>则为true。<ehost>可以是/etc/ethers里的一个名字或者数字。

ether src <ehost>

如果Ethernet源地址是<ehost>则为true。

ether host <ehost>

如果Ethernet源地址或者目标是址是<ehost>则为true。

gateway <host>

如果包使用<host>作为一个网关则为true。例如,Ethernet的源或者目标地址是<host>, 但是IP源和目标都不是<host><host>必须是一个名字,必须同时可以被机器的 host-name-to-IP-address解析机制(host name file, DNS, NIS等)和 host-name-to-Ethernet-address解析机制(/etc/ethers等)解释。一个等价的表达式是:

1
ether host <ehost> and not host <host>

这个语法在启动IPv6的机器上不能工作。

dst net <net>

如果包中IPv4/v6的目标地址的网络号是<net>则为true。<net>可能是一个名字(/etc/networks等), 或者一个网络号。一个IPv4的网络号可以写成四段点分制(例如192.168.1.0),三段点分制(例如192.168.1), 两段点分制(例如172.16)或者一个单独的数字(例如10)。四段点分制的掩码为255.255.255.255 (意味着是一个主机地址),三段点分制的掩码为255.255.255.0,二段点分制的掩码为255.255.0.0, 单独数字的掩码为255.0.0.0。一个IPv6的网络号必须完整写出,掩码为ff:ff:ff:ff:ff:ff:ff:ff, 所以IPv6的网络匹配真实的主机,一个网络匹配需要一个网络掩码长度。

src net <net>

如果包中IPv4/v6的源地址的网络号是<net>则为true。

net <net>

如果包中的源或者目标地址的网络号是<net>则为true。

net <net> mask <netmask>

如果IPv4地址使用<netmask>的掩码匹配<net>网络号则为true。可以使用srcdst修饰符。 这个请求对IPv6无效。

net <net>/<len>

如果IPv4/v6使用<len>宽度的掩码匹配<net>网络号则为true。可以使用srcdst修饰符。

dst port <port>

如果包是ip/tcp, ip/udp, ip6/tcp, ip6/udp并且目标端口为<port>则为true。 <port>可以是一个数字或者/etc/services中定义的名字。如果使用名字,则端口名和协议都会被检查。 如果使用数字或者模糊的名字,则只检查端口(例如,dst port 513会打印tcp/login和udp/who的通信, port domain会打印tcp/domain和udp/domain的通信)。

src port <port>

如果包的源端口为<port>则为true。

port <port>

如果包的源端口或者目标端口为<port>则为true。

dst portrange <port1>-<port2>

如果包是ip/tcp, ip/udp, ip6/tcp, ip6/udp并且目标端口在<port1><port2>之间则为true。

src portrange <port1>-<port2>

如果包的源端口在<port1><port2>之间则为true。

portrange <port1>-<port2>

如果源端口或者目标端口在<port1><port2>之间则为true。

任意以上的端口或者范围端口表达式前都可以跟tcp, udp关键字,例如:

1
tcp src port <port>

只匹配tcp的<port>端口的包。

less <length>

如果包长度小于等于<length>则为true。等价于:

1
len <= <length>

greater <length>

如果包长度大于等于<length>则为true。等价于:

1
len >= <length>

ip proto <protocol>

如果是<protocol>协议的IPv4包则为true。<protocol>可以是一个数字或者以下的名字 icmp, icmp6, igmp, igrp, pim, ah, esp, vrrp, udp, tcp。 注意tcp, udp, icmp也是关键字,所以需要使用反斜杠转义。

ip6 proto <protocol>

如果是<protocol>协议的IPv6包则为true。

proto <protocol>

如果是<protocol>协议的IPv4/v6包则为true。

tcp, udp, icmp

proto <protocol>的缩写。

ip6 protochain <protocol>

如果是IPv6的包,并且协议头包含<protocol>在它的协议头链中,则为true。例如:

1
ip6 protochain 6

匹配任意IPv6包含有TCP协议头在协议头链中。这个包可能包含,例如,鉴权头,路由头, hop-by-hop选项头等。

ip protochain <protocol>

等价于ip6 protochain <protocol>,但是是IPv4。

protochain <protocol>

等价于ip protochain <protocol> or ip6 protochain <protocol>

ether broadcast

如果是Ethernet广播包则为true。ether关键字是可选的。

ip broadcast

如果是一个IPv4广播包则为true。它检查所有0和所有1的广播会话,也查询子网掩码。

ether multicast

如果是一个Ethernet广播包则为true。ether关键字是可选的。这是ehter[0] & 1 != 0的简写。

ip multicast

如果是一个IPv4广播包则为true。

ip6 multicast

如果是一个IPv6广播包则为true。

ether proto <protocol>

如果包是ether的<protocol>协议则为true。<protocol>可以是一个数字或者 ip, ip6, arp, rarp, atalk, aarp, decnet, sca, lat, mopdl, moprc, iso, stp, ipx, netbeui。这些修饰符都是关键闻,需要使用反斜杠转义。

ip, ip6, arp, rarp, atalk, aarp, decnet, iso, stp, ipx, netbeui

1
ether proto <protocol>

的缩写。<protocol>是以上的一个值。

lat, moprc, mopdl

1
ether proto <protocol>

的缩写。<protocol>是以上的一个值。并不是所有使用pcap的程序都能解析这些协议。

decnet src <host>

如果DECNET源地址是<host>则为true。<host>可能是一个10.123类型的址或者一个DECNET主机名。

decnet dst <host>

如果DECNET的目标地址是<host>则为true。

decnet host <host>

如果DECNET的源或者目标地址是<host>则为true。

ifname <interface>

如果是通过指定的接口进来的包则为true。

on <interface>

ifname同义。

rnr <num>

如果包匹配PF rule number则为true。

rulenum <num>

rnr同义。

reason <code>

如果包匹配PF reason code则为true。已知的code有: match, badoffset, fragment, short, normalize, memory

rset <name>

如果包匹配PF ruleset name则为true。

ruleset <name>

rset同义。

srnr <num>

如果包匹配PF rule number则为true。

subrulenum <num>

srnr同义。

action <act>

如果PF使用一个特殊的action则为true。已经的action: pass, block, nat, rdr, binat, scrub

wlan ra <ehost>

如果IEEE 802.11 RA是<ehost>则为true。RA域会在所有的帧中使用,除了管理帧。

wlan ta <ehost>

如果IEEE 802.11 TA是<ehost>则为true。TA域会在所有的帧中使用,除了管理贴、CTS(Clear To Send)和 ACK控制帧。

wlan addr1 <ehost>

如果第一个IEEE 802.11地址是<ehost>则为true。

wlan addr2 <ehost>

如果第二个IEEE 802.11地址(如果存在)是<ehost>则为true。第二个地址域会有所有的帧中使用, 除了CTS(Clear To Send)和ACK控制帧。

wlan addr3 <ehost>

如果第三个IEEE 802.11地址(如果存在)是<ehost>则为true。第三个地址域会在管理帧和数据帧中使用, 控制帧中没有。

wlan addr4 <ehost>

如果第四个IEEE 802.11地址(如果存在)是<ehost>则为true。第四个地址域只有WDS(Wireless Distribution System)帧使用。

type <wlan_type>

如果IEEE 802.11帧类型匹配<wlan_type>则为true。合法的<wlan_type>有:mgt, ctl, data

type <wlan_type> subtype <wlan_subtype>

如果IEEE 802.11帧类型匹配<wlan_type>并且帧子类型匹匹配<wlan_subtype>则为true。

如果<wlan_type>mgt,则可用的<wlan_subtype>有:assoc-req, assoc-resp, reassoc-req, reassoc-resp, probe-req, probe-resp, beacon, atim, dissassoc, auth, deauth

如果<wlan_type>ctl,则可用的<wlan_subtype>有:ps-poll, rts, cts, ack, cf-end, cf-end-ack

如果<wlan_type>data,则可用的<wlan_subtype>有:data, data-cf-ack, data-cf-poll, data-cf-ack-poll, null, cf-ack, cf-poll, cf-ack-poll, qos-data, qos-data-cf-ack, qos-data-cf-poll, qps-data-cf-ack-poll, qos, qos-cf-poll, qos-cf-ack-poll

subtype <wlan_subtype>

如果IEEE 802.11帧的subtype匹配<wlan_subtype>,并且帧拥有这个<wlan_subtype>则为true。

dir <dir>

如果IEEE 802.11帧方向匹配<dir>则为true。可用的方向有:nods, tods, fromds, dstods, 或者是一个数字的值。

vlan [vlan_id]

如果是IEEE 802.1Q VLAN包则为true。如果指定[vlan_id],则需要包拥有的vlan_id才为true。

mpls [label_num]

如果是MPLS包则为true。如果指定[label_num],只有包拥有label_num的时候才为true。

pppoed

如果是一个PPP-over-Ethernet Discovery包(Ethernet type 0x8863)则为true。

pppoes [session_id]

如果是PPP-over-Ethernet Session包(Ethernet type 0x8864)则为ture。如果指定session_id, 只有包拥有session_id时才为true。

iso proto <protocol>

如果是一个拥有<protocol>协议的OSI包才为true。<protocol>可以是一个数字或者clnp, esis, isis

clnp, esis, isis

1
iso proto <protocol>

的简写。<protocol>是以上的一个值。

l1, l2, iih, lsp, snp, csnp, psnp

IS-IS PDU类型的简写。

vpi <n>

如果是一个ATM包则为true。对于Solaris上的SunATM,需要一个虚拟的路径标识符<n>

vci <n>

如果是一个ATM包则为true。对于Solaris上的SunATM,需要一个虚拟的频道标识符<n>

lane

如果是一个ATM包则为true。对于Solaris上的SunATM,需要是ATM LANE包。

llc

如果是一个ATM包则为true。对于Solaris上的SunATM,需要是LLC-encapsulated包。

oamf4s

如果是一个ATM包则为true。对于Solaris上的SunATM,需要是OAM F4 flow cell(VPI=0 & VCI=3)段。

oamf4e

如果是一个ATM包则为true。对于Solaris上的SunATM,需要是end-to-end OAM F4 flow cell(VPI=0 & VCI=4)段。

oamf4

如果是一个ATM包则为true。对于Solaris上的SunATM,需要是end-to-end OAM F4 flow cell(VPI=0 & (VCI=3 | VCI=4))段。

oam

如果是一个ATM包则为true。对于Solaris上的SunATM,需要是end-to-end OAM F4 flow cell(VPI=0 & (VCI=3 | VCI=4))段。

metac

如果是一个ATM包则为true。对于Solaris上的SunATM,需要meta signaling circuit(VPI=0 & VCI=1)。

bcc

如果是一个ATM包则为true。对于Solaris上的SunATM,需要broadcast signaling circuit(VPI=0 & VCI=2)。

sc

如果是一个ATM包则为true。对于Solaris上的SunATM,需要signaling circuit(VPI=0 & VCI=5)。

ilmic

如果是一个ATM包则为true。对于Solaris上的SunATM,需要ILMI circuit(VPI=0 & VCI=16)。

connectmsg

如果是一个ATM包则为true。对于Solaris上的SunATM,需要signaling circuit和Q.2931 Setup, Call Proceeding, Connect, Connect Ack, Release, Release Done message。

metaconnect

如果是一个ATM包则为true。对于Solaris上的SunATM,需要signaling circuit和Q.2931 Setup, Call Proceeding, Connect, Connect Ack, Release, Release Done message。

<expr> <relop> <expr>

关系表达式为真是为true。<relop>>, <, >=, <=, =, !=中的一个。 <expr>是一个算术表达式,由十进制常量组成(标准C语言语法),普通的两目操作符 [+, -, *, /, &, |, <<, >>],一个长度运算符,特殊的包访问器。所有的比较都是无符号的, 例如0x80000000和0xffffffff都>0。要访问包内的内容,使用以下的语法:

1
<proto> [<expr> : <size>]

<proto>是以下中的一个ether, fddi, tr, wlan, ppp, slip, link, ip, arp, rarp, tcp, udp, icmp, ip6, radio和表示协议层的下标运算。 (ether, fddi, wlan, tr, ppp, slip, link表明是链路层)。注意,tcp, udp 和其他上层协议只对IPv4有效,IPv6无效。字节位移相对于表示的协议层,它通过<expr>指定。 <size>是可选的表示需要的字节数。它可以是1, 2, 4或者默认的1。length关键字len给出包的长度。

例如,ether[0] & 1 != 0捕捉所有的广播包。ip[0] & 0xf != 5捕捉所有包含IPv4选项的包。 ip[6:2] & 0x1fff = 0捕捉unfragmented IPv4数据报和frag zero of fragmented IPv4数据报。 这个检查隐式作用于tcpudp下标操作。例如tcp[0]永远意味着tcp包着的第一个字节。

一些位移和域值可以使用名字替换数字。以下合法的的协议头域位移:icmptype(ICMP type field), icmpcode(ICMP code field), tcpflags (TCP flags field)。

icmptype可用的值有: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

tcpflags可用的值有:tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg

原语可以结合使用: 使用括号括起来一组原语和操作符,在shell上括号必转义。

非(!或者not)。
与(&&或者and)。
或(||或者or)。

非具有最高优先级。与或具有相同的优先级,从左到右的结合方向。

如果一个标识符没有指定关键字,则假设为最近的关键字。例如:

1
not host vs and ace

是以下的缩写

1
not host vs and host ace

不要跟以下搞混

1
not (host vs or ace)

例子

选择所有到达或者离开sundown主机的包

1
host sundown

选择主机helios与hot或者ace通信的包

1
host helios and \(hot or ade \)

选择所有在ace和非helios的ip包

1
ip host ade and not helios

选择所有的本地主机和主机在Berkeley的通信包

1
net ucb-ether

选择所有经过网络snup的tcp通信包

1
gateway snup and (port ftp or ftp-data)

选择源或者目标不到本地主机的通信

1
ip and not net localnet

选择开始和结束包(SYN和FIN包),不涉及本地主机的会话

1
tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net localnet

选择所有80端口的HTTP IPv4包。也就是说只打印包含数据的包,不包含SYN,FIN,ACK-only的包。

1
tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)

选择所有发送经过snup大于576 bytes的包

1
gateway sunp and ip[2:2] > 576

选择IP广播或者多播包,并且不经过Ethernet广播或者多播

1
ether[0] & 1 = 0 and ip[16] >= 224

选择所有的非echo请求响应ICMP包,也就是说非ping包:

1
icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply

相关文章