PCAP資料包過濾器設定 及 過濾表示式語法
通常我們只對特定網路通訊感興趣。比如我們只打算監聽Telnet服務(port 23)以捕獲使用者名稱和口令資訊。獲知對FTP(port 21)或DNS(UDP port 53)資料流感興趣。可以通過pcap_compile()和pcap_setfilter來設定資料流過濾規則(filter)
函式原型:
int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)
p:表示pcap會話控制代碼;
fp:存放編譯以後的規則;
str:規則表示式格式的過濾規則(filter),同tcpdump中的filter;
optimize:制定優化選項:0 false, 1 true;
netmask:監聽介面的網路掩碼;
返回值:-1表示操作失敗,其他值表成功。
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
p:表示pcap的會話控制代碼;
fp:表示經過編譯後的過濾規則;
返回值:-1表示操作失敗,其他值表成功。
示例程式碼:
#include <pcap.h>
...
pcap_t *handle;
char dev[] = "rl0";
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program filter;
char filter_app[] = "port 23";
bpf_u_int32 mask;
bpf_u_int32 net;
pcap_lookupnet(dev, &net, &mask, errbuf);
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
pcap_compile(handle, &filter, filter_app, 0, net);
pcap_setfilter(handle, &filter);
上面的程式碼裝置rl0上以混雜模式監聽所有發往或源自埠23的資料包。Pcap_lookupnet()函式返回給定介面的IP地址和子網掩碼。
【語法】
wpcap的過濾器是以已宣告的謂詞語法為基礎的。過濾器是一個ASCII字串,它包含了一個過濾表示式。pcap_compile()把這個表示式編譯成核心級的包過濾器。
這個表示式會選擇那些資料包將會被堆存。如果表示式沒有給出,那麼,網路上所有的包都會被核心過濾引擎所認可。不然,只有那些表示式為'true'的包才會被認可。
這個表示式包含了一個或多個原語。原語通常包含了id(名字或序列),這些id優先於限定詞。以下是三種不同的限定詞:
輸入(type)
指明瞭哪些東西是id所代表的。可能的輸入是host,net和port。比如:`host foo',`net 128.3',`port 20'。如果沒有輸入限定詞,就假定是host
方向(dir)
由id指明瞭一個特定的傳輸方向。可能的方向是src,dst,src or dst。比如,'src foo','dst net 128.3',`src or dst port ftp-data'。如果沒有指定,就假定是src or dst。如果沒有鏈路層(比如,像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','port53'等價於'(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'。如果要簡化輸入,我們可以把已列出的id限定詞省略。比如:`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資料包的目標域(destination field)為host時為true,host既可以是地址,也可以是名字。
src host host
當IPv4/v6資料包的源域(source field)為host時為true。
host host
當IPv4/v6資料包的源域(source field)或目標域(destination field)為host時為true。以上任何一個host表示式可以是ip,arp,rarp或ip6開頭,如下所示:
ip host host等價於:
ether proto ip and host host如果host是一個多IP地址,那麼每一個地址都會被匹配。
ether dst ehost
當乙太網的目的地址為ehost時為true。ehost可以是一個來自/etc/ether的名字,也可以是一個數字代號(參見 ethers(3N)for numeric format)。
ether src ehost
當乙太網的源地址為ehost時為true。
ether host ehost
當乙太網的目的地址,或源地址為ehost時為true。
gateway host
當host為閘道器時為true。即,乙太網源地址或目的地址是host,但源地址和目的地址不同時為host。host必須能被機器的主機-IP地址(host-name-to-IP-address)機制找到(如主機名檔案,DNS,NIS等),也能被主機-乙太網地址(host-name-to-Ethernet-address)機制找到(如/etc/ethers等)。例如:
ether host ehost and not host hosthost / 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地址是 net ,子網掩碼匹配 netmask 時為true。可能需要 src 或 dst加以限制。注意,這個語法不能應用於IPv6。
net net/len
當IP地址是 net ,子網掩碼連續1的個數為 len 時為true。可能需要 src 或 dst加以限制。
dst port port
當資料包是ip/tcp, ip/udp, ip6/tcp 或 ip6/udp,並且目的埠號是port時為true。port可以是數字,或是在/etc/services中被使用的名字。(參見 tcp(4P) and udp(4P))。如果使用名字,那麼埠號和協議都將被檢測。如果使用數字,或者一個不明確的名字,那麼只有埠號會被檢測。(比如:dst port 513將列印tcp/login資料流和udp/who資料流。port domain將列印tcp/domain的資料流和udp/domain的資料流)。
src port port
當源埠號是 port時為true。
port port
當源埠號或目的埠號為 port 時為true。以上任何一個port表示式可以以關鍵字tcp或udp開頭,如下所示:
tcp src port port只匹配源埠是 port 的tcp資料包。
less length
當資料包的長度小於等於length時為true。即:
len <= length.greater length
當資料包的長度大於等於length時為true。即:
len >= length.ip proto protocol
當資料包是IP資料包,並且它的協議型別為protocol時為true。protocol可以是一個數字,也可以是icmp, icmp6,igmp,igrp,pim,ah,esp,vrrp,udp 或 tcp中的一個。注意,tcp,udp, icmp是關鍵字,所以,它們要使用反斜槓()來轉義,就好比C-shell中的\。注意,這個原語不會去追蹤協議首部鏈。
ip6 proto protocol
當資料包是IPv6資料包,並且它的協議型別為protocol時為true。注意,這個原語不會去追蹤協議首部鏈。
ip6 protochain protocol
當資料包是IPv6資料包,並且,在它的協議首部鏈中,包含了protocol型別的協議首部時,為true。例如:
ip6 protochain 6能匹配所有的,擁有TCP協議首部的IPv6的資料包。在IPv6首部和TCP首部之間,可能包含認證首部,路由首部和跳數選項首部。由這個原語所生成的BPF(BSD Packet Filter,包過濾機制)碼是複雜的,而且不能被BPF優化器優化,所以,在某些程度上,它的速度比較慢。
ip protochain protocol
功能和 ip6 protochain protocol相同,只是這個應用於 IPv4。
ether broadcast
當資料包是乙太網廣播資料包時為true。關鍵字ether是可選的。
ip broadcast
當資料包是IP廣播資料包時為true。它會檢查所有的廣播,包括地址全是0的和地址全是1的,然後,檢查子網掩碼。
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, aarp,decnet, sca, lat, mopdl, moprc,iso, stp, ipx, netbeui中的一個。注意,這些符號也都是關鍵字,所以,他們都需要用反斜槓()轉義。
[在使用FDDI(比如'fddi protocol arp')和令牌環(比如'tr protocol arp')和其他大多數這種協議時,協議根據802.2邏輯鏈路控制(LLC)來識別,這些資訊通常在FDDI或令牌環首部的開始。
當需要識別大多數協議的標識,比如FDDI或令牌環時, Tcpdump只檢查LLC報頭的ID資料域,它們以SNAP格式儲存,並且,組織單位識別碼(Organizational Unit Identifier(OUI))為0x000000,以封裝乙太網。它不會檢查這個包是不是SNAP格式的,並在0x000000單元有OUI。
然而,iso是個特例,它會檢查LLC首部的目的服務存取點DSAP(Destination Service Access Point)和源服務存取點SSAP(Source Service Access Point),stp和netbeui會檢查LLC首部的DSAP,atalk會檢查資料包是不是SNAP格式的,並且OUI是不是0x080007。Appletalk 同樣如此。
在乙太網的例子中,tcpdump檢查大部分協議的乙太網型別欄位,iso,sap 和 netbeui除外,因為它們會檢查802.3幀,然後檢查LLC首部,就像它對FDDI和令牌環那樣。atalk,它檢查乙太網幀的Appletalk etype和SNAP格式的乙太網幀,arrp,它在乙太網幀中檢查Appletalk ARP etype,或是在OUI為0x000000的802.2 SNAP幀中查詢,還有ipx,他會在乙太網幀中檢查IPX etype,在LLC首部檢查IPX DSAP,沒有用802.3封裝的LLC首部的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, aarp, decnet, iso, stp, ipx, netbeui
縮寫是:
ether proto pp 是以上協議中的一個。
lat, moprc, mopdl
縮寫是:
ether proto pp 是以上協議中的一個。注意: tcpdump 目前並不知道,如何解析出這些協議。
vlan [vlan_id]
當資料包是IEEE 802.1Q VLAN資料包時為true。若[vlan_id]被指定,則僅當資料包為指定的vlan_id,值才為true。注意,在假設資料包為VLAN資料包的前提下,表示式中的第一個關鍵字vlan會改變剩餘表示式的解碼偏移量。
tcp, udp, icmp
縮寫是:
ip proto p or ip6 proto pp 是以上協議中的一個。
iso proto protocol
當資料包的協議型別為protocol的OSI資料包時值為true。Protocol可以是一個數字或以下名稱中的一個:clnp,esis或isis。
clnp, esis, isis
縮寫是:
iso proto pp 是以上協議中的一個。注意,tcpdump並不能完成這些協議的全部解析工作。
expr relop expr
若關係式如下:relop是 >, <, >=, <=, =, != 中的一個,並且expr是一個由正整常數(用標準C語言的語法表示),標準二進位制運算子[ +, -, *, /, &, | ],運算子的長度,和指定資料包存取,則值為true。要存取資料包內的資料,可以使用以下的語法:
proto [ expr : size ]
Proto 是 ether, fddi, tr, ip, arp, rarp, tcp, udp, icmp or 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 程式碼域), and 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的元字元,那麼用一個引數傳遞比較容易,最好把它括起來,多個引數在傳遞前,用空格連線起來。