1. 程式人生 > >tcpdump的基本用法之過濾表示式

tcpdump的基本用法之過濾表示式

上篇部落格寫了tcpdump選項的用法, 這篇部落格我們來看一下過濾表示式。

過濾表示式的man手冊:man pcap-filter

tcpdump在使用過濾表示式時,如有用了shell的萬用字元,需要用單引號引起來。

情形1:只抓udp的包

#tcpdump -i eth0 -c 10 'udp'

情形2:只想檢視源機器和目的機器的包

# tcpdump -i eth0 'dst 8.8.8.8'

tcpdump還支援使用and和or來進行搭配

如果沒有設定,預設是src or dst,就是源機器是8.8.8.8或者目的機器是8.8.8.8都行。

情形3:只想檢視目標機器埠是53或80的包

# tcpdump -i eth0 -c 3 'dst port 53 or dst port 80'

我們可以設定過濾型別,上面例子中我們使用了port這個型別,就是來指定埠。當然,tcpdump還支援如下的型別:
1 host:指定主機名或IP地址,例如’host roclinux.cn’或’host 202.112.18.34′
2 net :指定網路段,例如’arp net 128.3’或’dst net 128.3′
3 portrange:指定埠區域,例如’src or dst portrange 6000-6008′

如果我們沒有設定過濾型別,那麼預設是host。

情形4:我想抓到那些通過eth0網絡卡的,且來源是roclinux.cn伺服器或者目標是roclinux.cn伺服器的網路包

tcpdump -i eth0 'host roclinux.cn'

情形5:我想抓通過eth0網絡卡的,且roclinux.cn和baidu.com之間通訊的網路包,或者,roclinux.cn和qiyi.com之間通訊的網路包

tcpdump -i eth0 'host roclinux.cn and (baidu.com or qiyi.com)'

情形6:我想獲取使用ftp埠和ftp資料埠的網路包

tcpdump 'port ftp or ftp-data'

情形7:我想獲取roclinux.cn和baidu.com之間建立TCP三次握手中第一個網路包,即帶有SYN標記位的網路包,另外,目的主機不能是qiyi.com

tcpdump 'tcp[tcpflags] & tcp-syn != 0 and not dst host qiyi.com'

情形8:列印IP包長超過576位元組的網路包

tcpdump 'ip[2:2] > 576'

情形9:列印廣播包或多播包,同時資料鏈路層不是通過乙太網媒介進行的

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

proto [ expr : size],只要掌握了這個語法格式,相信大家就能看懂上面的三個稀奇古怪的表示式了。

proto就是protocol的縮寫,表示這裡要指定的是某種協議的名稱,比如ip、tcp、ether。其實proto這個位置,總共可以指定的協議型別有15個之多,包括:

  • ether – 鏈路層協議
  • fddi – 鏈路層協議
  • tr – 鏈路層協議
  • wlan – 鏈路層協議
  • ppp – 鏈路層協議
  • slip – 鏈路層協議
  • link – 鏈路層協議
  • ip
  • arp
  • rarp
  • tcp
  • udp
  • icmp
  • ip6
  • radio
  • expr

用來指定資料報偏移量,表示從某個協議的資料報的第多少位開始提取內容,預設的起始位置是0;而size表示從偏移量的位置開始提取多少個位元組,可以設定為1、2、4。
如果只設置了expr,而沒有設定size,則預設提取1個位元組。比如ip[2:2],就表示提取出第3、4個位元組;而ip[0]則表示提取ip協議頭的第一個位元組。
在我們提取了特定內容之後,我們就需要設定我們的過濾條件了,我們可用的“比較操作符”包括:>,<,>=,<=,=,!=,總共有6個。
好,掌握了上面內容之後,我可以很負責任的告訴你,你已經掌握了tcpdump過濾表示式的最重要語法了。我們先來小試牛刀,看一個例題:
    ip[0] & 0xf != 5
    IP協議的第0-4位,表示IP版本號,可以是IPv4(值為0100)或者IPv6(0110);第5-8位表示首部長度,單位是“4位元組”,如果首部長度為預設的20位元組的話,此值應為5,       即”0101″。ip[0]則是取這兩個域的合體。0xf中的0x表示十六進位制,f是十六進位制數,轉換成8位的二進位制數是“0000 1111”。而5是一個十進位制數,它轉換成8位二進位制數為”0000     0101″。

    有了上面這些分析,大家應該可以很清楚的知道,這個語句中!=的左側部分就是提取IP包首部長度域,如果首部長度不等於5,就滿足過濾條件。言下之意也就是說,要求IP包的首部中含有可選欄位。

    大家可能已經有所體會,在寫過濾表示式時,你需要把協議格式完全背在腦子裡,才能把表示式寫對。可這對大多數人來說,可能有些困難。為了讓tcpdump工具更人性化一些,有一些常用的偏移量,可以通過一些名稱來代替,比如icmptype表示ICMP協議的型別域、icmpcode表示ICMP的code域,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-ack, tcp-urg。
如果一個過濾表示式有多個過濾條件,那麼就需要使用邏輯符了,其中,!或not都可以表示“否定”,&&與and都可以表示“與”,而||與or都可以表示“或”

update:

抓取http包:

tcpdump -Xvvenn -i eth1 tcp[20:2]=0x4745 or tcp[20:2]=0x4854 -w tcpdump.cap 

0x4745 為"GET"前兩個字母"GE"。
0x4854 為"HTTP"前兩個字母"HT"。

tcp[20:2]表示tcp頭部從第20位元組開始提取兩個位元組。由於tcp頭部一共20個位元組,所以接下來的2個位元組就是資料的前兩個位元組。

我們抓取“GET”和"HTTP“即可。數值是它們ASCII碼的值。