tcpdump學習五分鐘系列文章(轉載)

 

本原創文章屬於《Linux大棚》博客。

博客地址爲http://roclinux.cn

文章作者爲roc。


其實tcpdump就好像一個神探,它有着夜視的絕技,在毫無光亮的環境中,也可以看到所有的東西。(好像在編美劇hero一般,哈哈)

在介紹tcpdump之前,要和你確認好幾個關鍵前提,否則的話,往後的內容您看起來會非常困難。
1 瞭解和使用過linux
2 掌握網絡七層協議及其作用
3 熟悉各層協議頭,重點是以太網/IP/TCP/UDP
4 瞭解交換機、路由器所對應的協議層,並知道兩者的異同點。

如果你有些忘記了,那麼強烈建議你翻出《計算機網絡》教材,先好好回憶一下,然後再進入到下面的內容…

==

正文:

                                               (一)

通俗的說,tcpdump是一個抓包工具,用於抓取互聯網上傳輸的數據包。
形象的說,tcpdump就好比是國家海關,駐紮在出入境的咽喉要道,凡是要入境和出境的集裝箱,海關人員總要打開箱子,看看裏面都裝了點啥。
學術的說,tcpdump是一種嗅探器(sniffer),利用以太網的特性,通過將網卡適配器(NIC)置於混雜模式(promiscuous)來獲取傳輸在網絡中的信息包。

【抓人生中的第一個包】

要用tcpdump抓包,請記住,一定要切換到root賬戶下,因爲只有root纔有權限將網卡變更爲“混雜模式”。
然後呢,就是用ifconfig的方法查看好你的服務器的網卡名稱。(我的叫做eth0,一般都是這個名字)

# tcpdump -i eth0 -nn -X ‘port 53′ -c 1
   
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
23:58:04.688155 IP 116.255.245.206.47172 > 61.139.2.69.53: 15352+ A? www.baidu.com. (31)
0x0000: 4500 003b d596 0000 4011 fa7d 74ff f5ce E..;....@..}t...
0x0010: 3d8b 0245 b844 0035 0027 a48f 3bf8 0100 =..E.D.5.'..;...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
1 packets captured
1 packets received by filter
0 packets dropped by kernel

在此,我重點解釋下這個命令:

-i選項:
是interface的含義,是指我們有義務告訴tcpdump希望他去監聽哪一個網卡。這在我們一臺服務器有多塊網卡時很有必要。

-nn選項:
意思是說當tcpdump遇到協議號或端口號時,不要將這些號碼轉換成對應的協議名稱或端口名稱。比如,衆所周知21端口是FTP端口,我們希望顯示21,而非tcpdump自作聰明的將它顯示成FTP。

-X選項:
告訴tcpdump命令,需要把協議頭和包內容都原原本本的顯示出來(tcpdump會以16進制和ASCII的形式顯示),這在進行協議分析時是絕對的利器。

‘port 53′:
這是告訴tcpdump不要看到啥就顯示啥。我們只關心源端口或目的端口是53的數據包,其他的數據包別給我顯示出來。

-c選項:
是Count的含義,這設置了我們希望tcpdump幫我們抓幾個包。我設置的是1,所以tcpdump不會幫我再多抓哪怕一個包回來。

【未完待續】

從混混亂亂的輸出中,大家一定隱約的能看到www.baidu.com,是的,我抓到的這個包,其實是DNS解析的第一個包,也就是發出解析請求的包。至於tcpdump輸出的內容到底是什麼含義,會在後面娓娓道來。敬請期待。
                                                  (二)
tcpdump可以分爲三大部分內容,第一是“選項”,第二是“過濾表達式”,第三是“輸出信息”。
下面的文章,會分別從這三個方面來重點介紹。
tcpdump的選項,我還真是專門數了一下,總共有50個之多。在這個系列文章中,實在很難全都覆蓋,我儘量挑選重要且常用的選項來講解,
一些不常用的選項,大家抽空可以自己去了解一下。

在《第一招》中講到了-i選項、-nn選項、-c選項、-X選項。今天,我們繼續介紹另外兩個重要的選項,即-e選項和-l選項。

【-e選項】- 增加以太網幀頭部信息輸出

閒言少敘,直接給出例子,大家就能看到區別了:
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:36:18.490875 IP 116.255.245.206.snapenetio > 61.135.169.73.56503: Flags [P.], seq 990974500:990974696, ack 4001909970, win 270, length 196
# tcpdump -i eth0 -c 1 -e
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:36:09.910296 00:15:5d:f5:4b:37 (oui Unknown) > 00:00:0c:07:ac:15 (oui Cisco), ethertype IPv4 (0x0800), length 250: 116.255.245.206.snapenetio > 61.135.169.73.56503: Flags [P.], seq 990973640:990973836, ack 4001909762, win 270, length 196

如果還是看不懂,說明你忘記了以太網協議的頭格式,我再這裏補充下,幫大家回憶回憶:
   
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* 目的主機的地址 */
u_char ether_shost[ETHER_ADDR_LEN]; /* 源主機的地址 */
u_short ether_type; /* IP? ARP? RARP? etc */
};

在剛纔加-e選項的輸出中,會發現有oui Unknown的字樣,這oui是什麼東東呢?在這裏順便科普一下咯:
OUI,即Organizationally unique identifier,是“組織唯一標識符”,在任何一塊網卡(NIC)中燒錄的6字節MAC地址中,前3個字節體現了OUI,其表明了NIC的製造組織。通常情況下,該標識符是唯一的。

【-l選項】- 使得輸出變爲行緩衝

-l選項的作用就是將tcpdump的輸出變爲“行緩衝”方式,這樣可以確保tcpdump遇到的內容一旦是換行符即將緩衝的內容輸出到標準輸出,以便於利用管道或重定向方式來進行後續處理。

衆所周知,Linux/UNIX的標準I/O提供了全緩衝、行緩衝和無緩衝三種緩衝方式。標準錯誤是不帶緩衝的,終端設備常爲行緩衝,而其他情況默認都是全緩衝的。

大家在使用tcpdump時,有時會有這樣的需求:“對於tcpdump輸出的內容,提取每一行的第一個域,即時間域,並輸出出來,爲後續統計所用”,這種場景下,我們就需要使用到-l來將默認的全緩衝變爲行緩衝了。
   
# tcpdump -i eth0 -l |awk '{print $1}'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
22:56:57.571680
22:56:57.572103
22:56:57.599515
22:56:57.706286
22:56:57.888108
22:56:57.888296
22:56:57.973546
22:56:57.973768
22:56:57.975660
22:56:58.019052
22:56:58.019318
^C146 packets captured
161 packets received by filter
0 packets dropped by kernel

如果不加-l選項,那麼只有全緩衝區滿,纔會輸出一次,這樣不僅會導致輸出是間隔不順暢的,而且當你ctrl-c時,很可能會斷到一行的半截,損壞統計數據的完整性。
                                                          (三)
==

上篇文章說過,tcpdump會分成“選項”、“過濾表達式”和“輸出信息”三部分講解。

截止到目前,我們一直在圍繞tcpdump的選項部分進行講解,已經介紹過的選項包括-i選項、-nn選項、-c選項、-X選項、-e選項、-l選項。
今天仍然不例外,我們繼續有關選項的內容。

==

【-t選項】- 輸出時不打印時間戳

這個選項非常好理解,直接看例子吧:
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:52:10.433391 ARP, Request who-has 116.255.247.61 tell 116.255.247.125, length 64
# tcpdump -i eth0 -c 1 -t
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
ARP, Request who-has 116.255.245.35 tell 116.255.245.62, length 64

【-v選項】- 輸出更詳細的信息

加了-v選項之後,在原有輸出的基礎之上,你還會看到tos值、ttl值、ID值、總長度、校驗值等。
至於上述值的含義,需要你專門去研究下IP頭、TCP頭的具體協議定義咯。

# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:53:09.162644 IP 116.255.245.206.snapenetio > 221.223.255.234.54198: Flags [P.], seq 1443040202:1443040398, ack 3517061690, win 353, length 196
# tcpdump -i eth0 -c 1 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:52:57.902894 IP (tos 0x10, ttl 64, id 18293, offset 0, flags [DF], proto TCP (6), length 172)
116.255.245.206.snapenetio > 221.223.255.234.54198: Flags [P.], cksum 0x4dd9 (correct), seq 1443039302:1443039434, ack 3517061430, win 353, length 132

【-F選項】- 指定過濾表達式所在的文件

還記得我們在第一招中所提到的命令麼,我幫助大家回憶一下:

 tcpdump -i eth0 -nn -X ‘port 53′ -c 1

這裏面的’port 53′便叫做“過濾表達式”,用於設置我們抓包的條件的,只有滿足過濾條件的網絡包,纔會被抓過來。
當這個過濾條件非常複雜,或者我們需要將一個過濾條件固化下來複用的時候,就會想到把它存到一個文本文件中。
此時,-F選項就會派上用場。請看例子:
   
# cat filter.txt
port 53
# tcpdump -i eth0 -c 1 -t -F filter.txt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
IP 116.255.245.206.54357 > ns.sc.cninfo.net.domain: 36720+ A? www.baidu.com. (31)
1 packets captured
6 packets received by filter
0 packets dropped by kernel

我們建立了一個filter.txt文本文件來存儲過濾表達式,然後通過-F來指定filter.txt,這樣tcpdump就會心知肚明地讀取filter.txt中的內容作爲過濾條件。

                                                 (四)
本文會是“選項內容”的最後一期講解,主要會講講-w和-r兩個選項。tcpdump的選項很多,多達50個,其他我沒有涉及的選項,還是要大家自己通過man tcpdump的方式來學習了。實在研究不懂的,可以找我探討:)

==

做過網絡流量分析的同學,或許都有一個共同的需求,那就是“流量保存”和“流量回放”,這就恰好對應了今天要講解的-w選項和-r選項。

“流量保存”就是把抓到的網絡包能存儲到磁盤上,保存下來,爲後續使用。

“流量回放”就是把歷史上的某一時間段的流量,重新模擬回放出來,用於流量分析。

【-w選項】- 將流量保存到文件中
# tcpdump -i eth0 -w flowdata
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
^C327 packets captured
327 packets received by filter
0 packets dropped by kernel

通過上面的例子可以看到,通過-w選項將流量都存儲在了flowdata文件中了。大家是否有興趣less下flowdata,看看裏面都是什麼東東?
# less flowdata
"flowdata" may be a binary file. See it anyway?

悲劇,原來都是二進制格式的,無法直接通過文本方式查看。嗯,買了個關子,把真像告訴大家吧!

tcpdump的-w方式是把raw packets(原始網絡包)直接存儲到文件中了,也就是存儲的都是結構體形式,而非是分析之後的文本格式的信息,因此大家是無法直接通過less命令查看的。

那麼,怎麼查看呢?大家想必也想到了,就是用-r選項。

【-r選項】- 讀取raw packets文件
# tcpdump -r flowdata
reading from file flowdata, link-type EN10MB (Ethernet)
16:43:36.202443 IP 116.255.245.206.snapenetio > 61.135.169.73.52414: Flags [P.], seq 4082702792:4082702924, ack 3248983965, win 291, length 132
16:43:36.222033 IP 61.135.169.73.52414 > 116.255.245.206.snapenetio: Flags [.], ack 132, win 61, length 0
16:43:36.277407 IP 116.255.245.62 > ospf-all.mcast.net: OSPFv2, Hello, length 48
16:43:36.370846 ARP, Request who-has 116.255.245.203 tell 116.255.245.254, length 64
16:43:36.521947 ARP, Request who-has 116.255.245.203 tell 116.255.245.253, length 64
16:43:36.635472 ARP, Request who-has 116.255.245.214 tell 116.255.245.253, length 64

其實上面的命令就是在不知不覺中進行了“流量回放”,你會發現網絡包被“抓”的速度都按照歷史進行了回放,真像一個“時光機”啊!

由於是按raw packets來存儲的,所以你完全可以使用-e、-l和過濾表達式來對輸出信息進行控制,十分方便。

==

預告,第五招開始,會講解過濾表達式了,會比較有意思,敬請期待。

                                           (五)

前四招都是圍繞tcpdump的選項來介紹的,從這招起,我們會把目光轉向更加常用的“過濾表達式”內容。

通過這幾招的學習,你將具備“心無旁騖,潛心專注”的武功。

==

【師傅領進門】

可以給tcpdump傳送“過濾表達式”來起到網絡包過濾的作用,而且可以支持傳入單個或多個過濾表達式,從這一點來說tcpdump還是很大肚能容的。
當你傳入的過濾表達式含有shell通配符時,別忘使用單引號把表達式括起來,以防shell自作主張的把含有通配符的表達式先進行了解釋和通配。

如果你希望自己研究“過濾表達式”,沒問題,我會告訴你如何“進門”,方法就是:

man pcap-filter

你會發現,過濾表達式大體可以分成三種過濾條件,“類型”、“方向”和“協議”,這三種條件的搭配組合就構成了我們的過濾表達式。

【我只想抓UDP的包,不想被TCP的包打擾】
# tcpdump -i eth0 -c 10 'udp'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:25:20.801612 IP 116.255.245.48.54808 > 229.111.112.12.csd-mgmt-port: UDP, length 4
11:25:20.802120 IP 116.255.245.206.54313 > ns.sc.cninfo.net.domain: 5256+ PTR? 12.112.111.229.in-addr.arpa. (45)
11:25:21.145126 IP ns.sc.cninfo.net.domain > 116.255.245.206.54313: 5256 NXDomain 0/0/0 (45)
11:25:21.145315 IP 116.255.245.206.46658 > ns.sc.cninfo.net.domain: 15551+ PTR? 48.245.255.116.in-addr.arpa. (45)
11:25:21.153966 IP 116.255.245.43.62220 > 229.111.112.12.csd-mgmt-port: UDP, length 4
11:25:21.180135 IP 116.255.245.61.hsrp > all-routers.mcast.net.hsrp: HSRPv0-hello 20: state=active group=21 addr=116.255.245.33
11:25:21.231151 IP ns.sc.cninfo.net.domain > 116.255.245.206.46658: 15551 NXDomain 0/0/0 (45)
11:25:21.231430 IP 116.255.245.206.46158 > ns.sc.cninfo.net.domain: 31924+ PTR? 69.2.139.61.in-addr.arpa. (42)
11:25:21.277087 IP ns.sc.cninfo.net.domain > 116.255.245.206.46158: 31924 1/0/0 PTR ns.sc.cninfo.net. (72)
11:25:21.277824 IP 116.255.245.206.42656 > ns.sc.cninfo.net.domain: 806+ PTR? 206.245.255.116.in-addr.arpa. (46)
10 packets captured
20 packets received by filter
0 packets dropped by kernel

舉這個例子,是爲了說明tcpdump具有根據網絡包的協議來進行過濾的能力,我們還可以把udp改爲ether、ip、ip6、arp、tcp、rarp等。
或許你會提問“爲啥這些協議裏沒有應用層協議呢?”,其實理由很簡單,應用層協議非基礎類網絡協議,經常會新增或淘汰,tcpdump不會深入到應用層部分去智能解析。所以,你現在看到的tcpdump支持的protocol都是應用層以下的。

【我想專門查看這個源機器和那個目的機器之間的網絡包,不想被其他無關的機器打擾】

這個其實很簡單,也很直觀,只要設置src(source)和dst(destination)就好了,而且方便的是,tcpdump還支持使用and和or來進行搭配組合呢!
如果沒有設置的話,默認是src or dst。
# tcpdump -i eth0 'dst 8.8.8.8'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:21:23.281978 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 1, length 64
13:21:24.286663 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 2, length 64
13:21:25.288612 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 3, length 64
^C
3 packets captured
5 packets received by filter
0 packets dropped by kernel

【我只想查目標機器端口是53或80的網絡包,其他端口的我不關注】
# tcpdump -i eth0 -c 3 'dst port 53 or dst port 80'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:29:04.530130 IP 114.255.192.96.29832 > 116.255.245.206.http: Flags [S], seq 3169042560, win 5840, options [mss 1460,sackOK,TS val 2949111416 ecr 0], length 0
13:29:04.530660 IP 116.255.245.206.43211 > ns.sc.cninfo.net.domain: 40188+ PTR? 206.245.255.116.in-addr.arpa. (46)
13:29:04.548589 IP 114.255.192.96.29832 > 116.255.245.206.http: Flags [.], ack 3709396068, win 5840, options [nop,nop,TS val 2949111475 ecr 1601243970], length 0
3 packets captured
10 packets received by filter
0 packets dropped by kernel

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

如果我們沒有設置過濾類型,那麼默認是host。 

                                              (六)

第六招,仍然會講解tcpdump的過濾表達式,這次思路很簡單,就是直接舉例子,其實就是man tcpdump中的例子,很直觀,很受用。

==

【例子1】- 我想抓到那些通過eth0網卡的,且來源是roclinux.cn服務器或者目標是roclinux.cn服務器的網絡包

tcpdump -i eth0 'host roclinux.cn'

【例子2】- 我想抓通過eth0網卡的,且roclinux.cn和baidu.com之間通訊的網絡包,或者,roclinux.cn和qiyi.com之間通訊的網絡包

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

【例子3】- 我想獲取使用ftp端口和ftp數據端口的網絡包

tcpdump 'port ftp or ftp-data'

大家是不是會有一個疑問“這個ftp、ftp-data到底對應哪個端口?除了ftp/ftp-data,還有哪些服務名稱我可以直接用呢?”

嗯,這是個好問題,答案現在揭曉咯。

在Linux系統中,/etc/services這個文件裏面,就存儲着所有知名服務和傳輸層端口的對應關係。這個對應關係是由IANA組織(the Internet Assigned Numbers Authority,互聯網數字分配機構)來全權負責的,你可以到這個鏈接http://www.iana.org/assignments/port-numbers通過Web方式查到。

如果你直接把/etc/services裏的ftp對應的端口值從21改爲了8888,那麼tcpdump就會去抓端口含有8888的網絡包了。

【例子4】- 我想獲取roclinux.cn和baidu.com之間建立TCP三次握手中第一個網絡包,即帶有SYN標記位的網絡包,另外,目的主機不能是qiyi.com

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

這個語句看着比較複雜,其實如果要把這段解釋清楚的確不容易,需要你具備計算機網絡專業知識才行。這個我會安排一招來講。

【例子5】- 打印IP包長超過576字節的網絡包

tcpdump 'ip[2:2] > 576'

【例子6】- 打印廣播包或多播包,同時數據鏈路層不是通過以太網媒介進行的。

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

最後三個例子,或許你看得有些暈頭轉向,沒關係,先有個感官認識,看完接下來的幾篇文章後,相信保證你就明白了:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章