一份快速實用的 tcpdump 命令參考手冊

對於 tcpdump 的使用,大部分管理員會分紅兩類。有一類管理員,他們熟知  tcpdump 和其中的全部標記;另外一類管理員,他們僅瞭解基本的使用方法,剩下事情都要藉助參考手冊才能完成。出現這種狀況的緣由在於, tcpdump 是一個至關高級的命令,使用的時候須要對網絡的工做機制有至關深刻的瞭解。 html

在今天的文章中,我想提供一個快速但至關實用的 tcpdump 參考。我會談到基本的和一些高級的使用方法。我敢確定我會忽略一些至關酷的命令,歡迎你補充在評論部分。 web

在咱們深刻了解之前,最重要的是瞭解  tcpdump 是用來作什麼的。 tcpdump 命令用來保存和記錄網絡流量。你能夠用它來觀察網絡上發生了什麼,並可用來解決各類各樣的問題,包括和網絡通訊無關的問題。除了網絡問題,我常常用 tcpdump 解決應用程序的問題。若是你發現兩個應用程序之間沒法很好工做,能夠用  tcpdump  觀察出了什麼問題。 tcpdump 能夠用來抓取和讀取數據包,特別是當通訊沒有被加密的時候。 緩存

基礎知識

瞭解 tcpdump ,首先要知道 tcpdump中使用的標記(flag)。在這個章節中,我會涵蓋到不少基本的標記,這些標記在不少場合下會被用到。 bash

1.不轉換主機名、端口號等

tcpdump -n

一般狀況下, tcpdump  會嘗試查找和轉換主機名和端口號。 服務器

# tcpdump
tcpdump: verbose output suppressed, use - v or -vv for full protocol decode
listening on eth0, link- type EN10MB (Ethernet), capture size 65535 bytes
16:15:05.051896 IP blog. ssh > 10.0.3.1.32855: Flags [P.], seq 2546456553:2546456749, ack 1824683693, win 355, options [nop,nop,TS val 620879437 ecr 620879348], length 196

你能夠經過 -n 標記關閉這個功能。我我的老是使用這個標記,由於我喜歡使用 IP 地址而不是主機名,主機名和端口號的轉換常常會帶來困擾。

可是,知道利用  tcpdump  轉換或者不轉換的功能仍是至關有用的,特別是有些時候,知道源流量(source traffic)來自哪一個服務器是至關重要的。


2.增長詳細信息

tcpdump -v

增長一個簡單 -v 標記,輸出會包含更多信息,例如一個 IP 包的生存時間(ttl, time to live)、長度和其餘的選項。
tcpdump  的詳細信息有三個等級,你能夠經過在命令行增長 v 標記的個數來獲取更多的信息。一般我在使用 tcpmdump 的時候,
老是使用最高等級的詳細信息,由於我但願看到全部信息,以避免後面會用到。


3.指定網絡接口

tcpdump -i eth0

一般狀況下,若是不指定網絡接口, tcpdump  在運行時會選擇編號最低的網絡接口,通常狀況下是 eth0,不過因系統不一樣可能會有所差別。
你能夠用 -i 標記來指定網絡接口。在大多數 Linux 系統上,any 這一特定的網絡接口名用來讓  tcpdump  監聽全部的接口。
我發現這在排查服務器(擁有多個網絡接口)的問題特別有用,尤爲是牽扯到路由的時候。


4.寫入文件

tcpdump -w /path /to/file
tcpdump  運行結果會輸出在屏幕上。

但不少時候,你但願把  tcpdump  的輸出結果保存在文件中,最簡單的方法就是利用 -w 標記。若是你後續還會檢查這些網絡數據,這樣作就特別有用。將這些數據存成一個文件的好處,就是你能夠屢次讀取這個保存下來的文件,而且能夠在這個網絡流量的快照上使用其它標記或者過濾器(咱們後面會討論到)。

一般這些數據被緩存而不會被寫入文件,直到你用 CTRL+C 結束 tcpdump 命令的時候。

5.讀取文件

tcpdump -r /path/to/file
一旦你將輸出存成文件,就必然須要讀取這個文件。要作到這點,你只須要在 -r 標記後指定這個文件的存放路徑。
一個小提醒,若是你熟悉 wireshark 這類網絡診斷工具,也能夠利用它們來讀取  tcpdump  保存的文件。

6.指定抓包大小

tcpdump -s 100
較新版本的  tcpdump  一般能夠截獲 65535 字節,但某些狀況下你不須要截獲默認大小的數據包。運行  tcpdump  時,
你能夠經過 -s 標記來指定快照長度。

7.指定抓包數量

tcpdump -c 10
tcpdump  會一直運行,直至你用 CTRL+C 讓它退出。
你也能夠經過 -c 標記後面加上抓包的數量,讓  tcpdump  在抓到必定數量的數據包後中止操做。當你不但願看到  tcpdump  的輸出大量出如今屏幕上,以致於你沒法閱讀的時候,就會但願使用這個標記。固然,一般更好的方法是藉助過濾器來截獲特定的流量。


8.基礎知識彙總

tcpdump -nvvv -i  any   -s 100 -c 100
你能夠將以上這些基礎的標記組合起來使用,來讓  tcpdump  提供你所須要的信息。


=======================================================================================

過濾器

介紹完基礎的標記後,咱們該介紹過濾器了。 tcpdump  能夠經過各式各樣的表達式,來過濾所截取或者輸出的數據。我在這篇文章裏會給出一些簡單的例子,以便讓大家瞭解語法規則。大家能夠查詢  tcpdump  幫助中的 pcap-filter 章節,瞭解更爲詳細的信息。 網絡


9.查找特定主機的流量

tcpdump -nvvv -i any -c 3 host 10.3.3.1
運行上述命令, tcpdump  會像前面同樣把結果輸出到屏幕上,不過只會顯示源 IP 或者目的 IP 地址是 10.0.3.1 的數據包。經過增長主機 10.0.3.1 參數,咱們可讓  tcpdump  過濾掉源和目的地址不是 10.0.3.1 的數據包。

10.只顯示源地址爲特定主機的流量

tcpdump -nvvv -i any -c 3 src host 10.0.3.1
前面的例子顯示了源和目的地址是 10.0.3.1 的流量,而上面的命令只顯示數據包源地址是 10.0.3.1 的流量。這是經過在 host 前面增長 src 參數來實現的。這個額外的過濾器告訴  tcpdump  查找特定的源地址。 反過來經過 dst 過濾器,能夠指定目的地址。

11.過濾源和目的端口

tcpdump -nvvv -i any -c 3 port 22 and port 60738

經過相似 and 操做符,你能夠在  tcpdump  上使用更爲複雜的過濾器描述。這個就相似 if 語句,你就這麼想吧。這個例子中,咱們使用 and 操做符告訴  tcpdump  只輸出端口號是 22 和 60738 的數據包。這點在分析網絡問題的時候頗有用,由於能夠經過這個方法來關注某一個特定會話(session)的數據包。

你能夠用兩種方式來表示 and 操做符,and 或者 && 均可以。我我的傾向於兩個都使用,特別要記住在使用 && 的時候,要用單引號或者雙引號包住表達式。在 BASH 中,你可使用 && 運行一個命令,該命令成功後再執行後面的命令 。一般,最好將表達式用引號包起來,這樣會避免不預期的結果,特別當過濾器中有一些特殊字符的時候。

12.查找兩個端口號的流量

tcpdump -nvvv -i any -c 20 'port 80 or port 443'
你能夠用 or 或者 || 操做符來過濾結果。在這個例子中,咱們使用 or 操做符去截獲發送和接收端口爲 80 或 443 的數據流。這在 Web 服務器上特別有用,由於服務器一般有兩個開放的端口,端口號 80 表示 http 鏈接,443 表示 https。


13.查找兩個特定端口和來自特定主機的數據流

tcpdump -nvvv -i any -c 20 '(prot 80 or port 443) and host 10.0.3.169'
前面的例子用來排查多端口的協議問題,是很是有效的。若是 Web 服務器的數據流量至關大, tcpdump  的輸出可能有點混亂。咱們能夠經過增長 host 參數進一步限定輸出。在這種狀況下,咱們經過把 or 表達式放在括號中來保持 or 描述。

在一個過濾器中,你能夠屢次使用括號。在下面的例子中,下面命令能夠限定截獲知足以下條件的數據包:發送或接收端口號爲 80 或 443,主機來源於 10.0.3.169 或者 10.0.3.1,且目的地址是 10.0.3.246。

================================================================================================

理解輸出結果

打開tcpdump的全部選項去截獲網絡流量是至關困難的,但一旦你拿到這些數據你就要對它進行解讀。在這個章節,咱們將涉及如何判斷源/目的 IP 地址,源/目的端口號,以及 TCP 協議類型的數據包。固然這些是至關基礎的,你從  tcpdump  裏面獲取的信息也遠不止這些。不過這篇文章主要是粗略的介紹,咱們會關注在這些基礎知識上。我建議大家能夠經過幫助頁獲取更爲詳細的信息。 session

14.判斷源和目的地址

判斷源和目的地址和端口號至關簡單。 app

從上面的輸出,咱們能夠看到源 IP 地址是 10.0.3.246,源端口號是 56894, 目的 IP 地址是 192.168.0.92,端口號是 22。一旦你理解  tcpdump  格式後,這些信息很容易判斷。若是你尚未猜到格式,你能夠按照 src-ip.src-port > dest-ip.dest-port: Flags[S] 格式來分析。源地址位於 > 前面,後面則是目的地址。你能夠把 > 想象成一個指向目的地址的箭頭符號。 ssh

15.判斷數據包類型


10.0.3.246.56894 > 192.168.0.92.22: Flags [S], cksum 0xcf28 (incorrect -> 0x0388), seq 682725222, win 29200, options [mss 1460,sackOK,TS val 619989005 ecr 0,nop,wscale 7], length 0

從上面的例子,咱們能夠判斷這個數據包是一個 SYN 數據包。咱們是經過  tcpdump  輸出中的 [S] 標記字段得出這個結論,不一樣類型的數據包有不一樣類型的標記。不須要深刻了解 TCP 協議中的數據包類型,你就能夠經過下面的速查表來加以判斷。 tcp

  • [S] – SYN (開始鏈接)
  • [.] – 沒有標記
  • [P] – PSH (數據推送)
  • [F] – FIN (結束鏈接)
  • [R] – RST (重啓鏈接)

在這個版本的  tcpdump  輸出中,[S.] 標記表明這個數據包是 SYN-ACK 數據包。

16.很差的例子

15:15:43.323412 IP (tos 0x0, ttl 64, id 51051, offset 0, flags [DF], proto TCP (6), length 60)
     10.0.3.246.56894 > 192.168.0.92.22: Flags [S], cksum 0xcf28 (incorrect -> 0x0388), seq 682725222, win 29200, options [mss 1460,sackOK,TS val 619989005 ecr 0,nop,wscale 7], length 0
15:15:44.321444 IP (tos 0x0, ttl 64, id 51052, offset 0, flags [DF], proto TCP (6), length 60)
     10.0.3.246.56894 > 192.168.0.92.22: Flags [S], cksum 0xcf28 (incorrect -> 0x028e), seq 682725222, win 29200, options [mss 1460,sackOK,TS val 619989255 ecr 0,nop,wscale 7], length 0
15:15:46.321610 IP (tos 0x0, ttl 64, id 51053, offset 0, flags [DF], proto TCP (6), length 60)
     10.0.3.246.56894 > 192.168.0.92.22: Flags [S], cksum 0xcf28 (incorrect -> 0x009a), seq 682725222, win 29200, options [mss 1460,sackOK,TS val 619989755 ecr 0,nop,wscale 7], length 0

上面顯示了一個很差的通訊例子,在這個例子中「很差」,表明通訊沒有創建起來。咱們能夠看到 10.0.3.246 發出一個 SYN 數據包給 主機 192.168.0.92,可是主機並無應答。

17.好的例子


15:18:25.716453 IP (tos 0x10, ttl 64, id 53344, offset 0, flags [DF], proto TCP (6), length 60)
     10.0.3.246.34908 > 192.168.0.110.22: Flags [S], cksum 0xcf3a (incorrect -> 0xc838), seq 1943877315, win 29200, options [mss 1460,sackOK,TS val 620029603 ecr 0,nop,wscale 7], length 0
15:18:25.716777 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60)
     192.168.0.110.22 > 10.0.3.246.34908: Flags [S.], cksum 0x594a (correct), seq 4001145915, ack 1943877316, win 5792, options [mss 1460,sackOK,TS val 18495104 ecr 620029603,nop,wscale 2], length 0
15:18:25.716899 IP (tos 0x10, ttl 64, id 53345, offset 0, flags [DF], proto TCP (6), length 52)
     10.0.3.246.34908 > 192.168.0.110.22: Flags [.], cksum 0xcf32 (incorrect -> 0x9dcc), ack 1, win 229, options [nop,nop,TS val 620029603 ecr 18495104], length 0

好的例子應該向上面這樣,咱們看到典型的 TCP 3次握手。第一數據包是 SYN 包,從主機 10.0.3.246 發送給 主機192.168.0.110,第二個包是 SYN-ACK 包,主機192.168.0.110 迴應 SYN 包。最後一個包是一個 ACK 或者 SYN – ACK – ACK 包,是主機 10.0.3.246 迴應收到了 SYN – ACK 包。從上面看到一個 TCP/IP 鏈接成功創建。

=======================================================================

數據包檢查

18.用十六進制和 ASCII 碼打印數據包

tcpdump -nvvv -i any -c 1 -XX 'port 80 and host 10.0.3.1'
排查應用程序網絡問題的一般作法,就是用  tcpdump  的 -XX 標記打印出 16 進制和 ASCII 碼格式的數據包。這是一個至關有用的命令,它可讓你看到源地址,目的地址,數據包類型以及數據包自己。但我不是這個命令輸出的粉絲,我認爲它太難讀了。

19.只打印 ASCII 碼格式的數據包

tcpdump -nvvv -i any -c 1 -A 'port 80 and host 10.0.3.1'
我傾向於只打印 ASCII 格式數據,這能夠幫助我快速定位數據包中發送了什麼,哪些是正確的,哪些是錯誤的。你能夠經過 -A 標記來實現這一點。
tcpdump -nvvv -i any -c 1 -A 'port 80 and host 10.0.3.1'
tcpdump: listening on any, link- type LINUX_SLL (Linux cooked), capture size 65535 bytes
19:59:52.011337 IP (tos 0x0, ttl 64, id 53757, offset 0, flags [DF], proto TCP (6), length 406)
     10.0.3.1.46172 > 10.0.3.246.80: Flags [P.], cksum 0x1c7f (incorrect -> 0xead1), seq 1552520173:1552520527, ack 428165415, win 237, options [nop,nop,TS val 624251177 ecr 624247749], length 354
...
....\.P\.....I'...........
%5Q)%5C.GET /newpage HTTP /1 .1
Host: 10.0.3.246
Connection: keep-alive
Accept: text /html ,application /xhtml +xml,application /xml ;q=0.9,image /webp ,*/*;q=0.8
User-Agent: Mozilla /5 .0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit /537 .36 (KHTML, like Gecko) Chrome /38 .0.2125.101 Safari /537 .36
Accept-Encoding: gzip ,deflate,sdch
Accept-Language: en-US,en;q=0.8

從上面的輸出,你能夠看到咱們成功獲取了一個 http 的 GET 請求包。若是網絡通訊沒有被加密,用人類可閱讀的格式打出包中數據,對於解決應用程序的問題是頗有幫助。若是你排查一個網絡通訊被加密的問題,打印包中數據就不是頗有用。不過若是你有證書的話,你仍是可使用 ssldump 或者 wireshark

===================================================================

非 TCP 數據流

雖然這篇文章主要採用 TCP 傳輸來說解  tcpdump ,可是  tcpdump  絕對不是隻能抓 TCP 數據包。它還能夠用來獲取其餘類型的數據包,例如 ICMP、 UDP 和 ARP 包。下面是一些簡單的例子,說明  tcpdump  能夠截獲非 TCP 數據包。

20.ICMP 數據包

tcpdump -nvvv -i any -c 2 icmp

tcpdump: listening on any, link- type LINUX_SLL (Linux cooked), capture size 65535 bytes
20:11:24.627824 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
     10.0.3.169 > 10.0.3.246: ICMP echo request, id 15683, seq 1, length 64
20:11:24.627926 IP (tos 0x0, ttl 64, id 31312, offset 0, flags [none], proto ICMP (1), length 84)
     10.0.3.246 > 10.0.3.169: ICMP echo reply, id 15683, seq 1, length 64



21.UDP 數據包

tcpdump -nvvv -i any -c 2 udp

tcpdump: listening on any, link- type LINUX_SLL (Linux cooked), capture size 65535 bytes
20:12:41.726355 IP (tos 0xc0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 76)
     10.0.3.246.123 > 198.55.111.50.123: [bad udp cksum 0x43a9 -> 0x7043!] NTPv4, length 48
         Client, Leap indicator: clock unsynchronized (192), Stratum 2 (secondary reference), poll 6 (64s), precision -22
         Root Delay: 0.085678, Root dispersion: 57.141830, Reference-ID: 199.102.46.75
           Reference Timestamp:  3622133515.811991035 (2014 /10/12 20:11:55)
           Originator Timestamp: 3622133553.828614115 (2014 /10/12 20:12:33)
           Receive Timestamp:    3622133496.748308420 (2014 /10/12 20:11:36)
           Transmit Timestamp:   3622133561.726278364 (2014 /10/12 20:12:41)
             Originator - Receive Timestamp:  -57.080305658
             Originator - Transmit Timestamp: +7.897664248
20:12:41.748948 IP (tos 0x0, ttl 54, id 9285, offset 0, flags [none], proto UDP (17), length 76)
     198.55.111.50.123 > 10.0.3.246.123: [udp sum ok] NTPv4, length 48
         Server, Leap indicator:  (0), Stratum 3 (secondary reference), poll 6 (64s), precision -20
         Root Delay: 0.054077, Root dispersion: 0.058944, Reference-ID: 216.229.0.50
           Reference Timestamp:  3622132887.136984840 (2014 /10/12 20:01:27)
           Originator Timestamp: 3622133561.726278364 (2014 /10/12 20:12:41)
           Receive Timestamp:    3622133618.830113530 (2014 /10/12 20:13:38)
           Transmit Timestamp:   3622133618.830129086 (2014 /10/12 20:13:38)
             Originator - Receive Timestamp:  +57.103835195
             Originator - Transmit Timestamp: +57.103850722
相關文章
相關標籤/搜索