在 Linux 命令列中使用 tcpdump 抓包

2018-11-04 00:20:00

tcpdump 是一款靈活、功能強大的抓包工具,能有效地幫助排查網路故障問題。

以我作為管理員的經驗,在網路連線中經常遇到十分難以排查的故障問題。對於這類情況,tcpdump 便能派上用場。

tcpdump 是一個命令列實用工具,允許你抓取和分析經過系統的流量封包。它通常被用作於網路故障分析工具以及安全工具。

tcpdump 是一款強大的工具,支援多種選項和過濾規則,適用場景十分廣泛。由於它是命令列工具,因此適用於在遠端伺服器或者沒有圖形介面的裝置中收集封包以便於事後分析。它可以在後台啟動,也可以用 cron 等定時工具建立定時任務啟用它。

本文中,我們將討論 tcpdump 最常用的一些功能。

1、在 Linux 中安裝 tcpdump

tcpdump 支援多種 Linux 發行版,所以你的系統中很有可能已經安裝了它。用下面的命令檢查一下是否已經安裝了 tcpdump

$ which tcpdump/usr/sbin/tcpdump

如果還沒有安裝 tcpdump,你可以用軟體包管理器安裝它。 例如,在 CentOS 或者 Red Hat Enterprise 系統中,用如下命令安裝 tcpdump

$ sudo yum install -y tcpdump

tcpdump 依賴於 libpcap,該庫檔案用於捕獲網路封包。如果該庫檔案也沒有安裝,系統會根據依賴關係自動安裝它。

現在你可以開始抓包了。

2、用 tcpdump 抓包

使用 tcpdump 抓包,需要管理員許可權,因此下面的範例中絕大多數命令都是以 sudo 開頭。

首先,先用 tcpdump -D 命令列出可以抓包的網路介面:

$ sudo tcpdump -D1.eth02.virbr03.eth14.any (Pseudo-device that captures on all interfaces)5.lo [Loopback]

如上所示,可以看到我的機器中所有可以抓包的網路介面。其中特殊介面 any 可用於抓取所有活動的網路介面的封包。

我們就用如下命令先對 any 介面進行抓包:

$ sudo tcpdump -i anytcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes09:56:18.293641 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 3770820720:3770820916, ack 3503648727, win 309, options [nop,nop,TS val 76577898 ecr 510770929], length 19609:56:18.293794 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 196, win 391, options [nop,nop,TS val 510771017 ecr 76577898], length 009:56:18.295058 IP rhel75.59883 > gateway.domain: 2486+ PTR? 1.64.168.192.in-addr.arpa. (43)09:56:18.310225 IP gateway.domain > rhel75.59883: 2486 NXDomain* 0/1/0 (102)09:56:18.312482 IP rhel75.49685 > gateway.domain: 34242+ PTR? 28.64.168.192.in-addr.arpa. (44)09:56:18.322425 IP gateway.domain > rhel75.49685: 34242 NXDomain* 0/1/0 (103)09:56:18.323164 IP rhel75.56631 > gateway.domain: 29904+ PTR? 1.122.168.192.in-addr.arpa. (44)09:56:18.323342 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 196:584, ack 1, win 309, options [nop,nop,TS val 76577928 ecr 510771017], length 38809:56:18.323563 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 584, win 411, options [nop,nop,TS val 510771047 ecr 76577928], length 009:56:18.335569 IP gateway.domain > rhel75.56631: 29904 NXDomain* 0/1/0 (103)09:56:18.336429 IP rhel75.44007 > gateway.domain: 61677+ PTR? 98.122.168.192.in-addr.arpa. (45)09:56:18.336655 IP gateway.domain > rhel75.44007: 61677* 1/0/0 PTR rhel75. (65)09:56:18.337177 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 584:1644, ack 1, win 309, options [nop,nop,TS val 76577942 ecr 510771047], length 1060---- SKIPPING LONG OUTPUT -----09:56:19.342939 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 1752016, win 1444, options [nop,nop,TS val 510772067 ecr 76578948], length 0^C9003 packets captured9010 packets received by filter7 packets dropped by kernel$

tcpdump 會持續抓包直到收到中斷信號。你可以按 Ctrl+C 來停止抓包。正如上面範例所示,tcpdump 抓取了超過 9000 個封包。在這個範例中,由於我是通過 ssh 連線到伺服器,所以 tcpdump 也捕獲了所有這類封包。-c 選項可以用於限制 tcpdump 抓包的數量:

$ sudo tcpdump -i any -c 5tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes11:21:30.242740 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 3772575680:3772575876, ack 3503651743, win 309, options [nop,nop,TS val 81689848 ecr 515883153], length 19611:21:30.242906 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 196, win 1443, options [nop,nop,TS val 515883235 ecr 81689848], length 011:21:30.244442 IP rhel75.43634 > gateway.domain: 57680+ PTR? 1.64.168.192.in-addr.arpa. (43)11:21:30.244829 IP gateway.domain > rhel75.43634: 57680 NXDomain 0/0/0 (43)11:21:30.247048 IP rhel75.33696 > gateway.domain: 37429+ PTR? 28.64.168.192.in-addr.arpa. (44)5 packets captured12 packets received by filter0 packets dropped by kernel$

如上所示,tcpdump 在抓取 5 個封包後自動停止了抓包。這在有些場景中十分有用 —— 比如你只需要抓取少量的封包用於分析。當我們需要使用過濾規則抓取特定的封包(如下所示)時,-c 的作用就十分突出了。

在上面範例中,tcpdump 預設是將 IP 地址和埠號解析為對應的介面名以及服務協定名稱。而通常在網路故障排查中,使用 IP 地址和埠號更便於分析問題;用 -n 選項顯示 IP 地址,-nn 選項顯示埠號:

$ sudo tcpdump -i any -c5 -nntcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes23:56:24.292206 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 166198580:166198776, ack 2414541257, win 309, options [nop,nop,TS val 615664 ecr 540031155], length 19623:56:24.292357 IP 192.168.64.1.35110 > 192.168.64.28.22: Flags [.], ack 196, win 1377, options [nop,nop,TS val 540031229 ecr 615664], length 023:56:24.292570 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 615664 ecr 540031229], length 37223:56:24.292655 IP 192.168.64.1.35110 > 192.168.64.28.22: Flags [.], ack 568, win 1400, options [nop,nop,TS val 540031229 ecr 615664], length 023:56:24.292752 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 568:908, ack 1, win 309, options [nop,nop,TS val 615664 ecr 540031229], length 3405 packets captured6 packets received by filter0 packets dropped by kernel

如上所示,抓取的封包中顯示 IP 地址和埠號。這樣還可以阻止 tcpdump 發出 DNS 查詢,有助於在網路故障排查中減少資料流量。

現在你已經會抓包了,讓我們來分析一下這些抓包輸出的含義吧。

3、理解抓取的報文

tcpdump 能夠抓取並解碼多種協定型別的資料包文,如 TCP、UDP、ICMP 等等。雖然這裡我們不可能介紹所有的資料包文型別,但可以分析下 TCP 型別的資料包文,來幫助你入門。更多有關 tcpdump 的詳細介紹可以參考其 幫助手冊tcpdump 抓取的 TCP 報文看起來如下:

08:41:13.729687 IP 192.168.64.28.22 > 192.168.64.1.41916: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 117964079 ecr 816509256], length 372

具體的欄位根據不同的報文型別會有不同,但上面這個例子是一般的格式形式。

第一個欄位 08:41:13.729687 是該資料包文被抓取的系統本地時間戳。

然後,IP 是網路層協定型別,這裡是 IPv4,如果是 IPv6 協定,該欄位值是 IP6

192.168.64.28.22 是源 ip 地址和埠號,緊跟其後的是目的 ip 地址和其埠號,這裡是 192.168.64.1.41916

在源 IP 和目的 IP 之後,可以看到是 TCP 報文標記段 Flags [P.]。該欄位通常取值如下:

標誌型別描述
SSYNConnection Start
FFINConnection Finish
PPUSHData push
RRSTConnection reset
.ACKAcknowledgment

該欄位也可以是這些值的組合,例如 [S.] 代表 SYN-ACK 封包。

接下來是該封包中資料的序列號。對於抓取的第一個封包,該欄位值是一個絕對數位,後續包使用相對數值,以便更容易查詢跟蹤。例如此處 seq 196:568 代表該封包包含該資料流的第 196 到 568 位元組。

接下來是 ack 值:ack 1。該封包是資料傳送方,ack 值為 1。在資料接收方,該欄位代表資料流上的下一個預期位元組資料,例如,該資料流中下一個封包的 ack 值應該是 568。

接下來欄位是接收視窗大小 win 309,它表示接收緩衝區中可用的位元組數,後跟 TCP 選項如 MSS(最大段大小)或者視窗比例值。更詳盡的 TCP 協定內容請參考 Transmission Control Protocol(TCP) Parameters

最後,length 372 代表封包有效載荷位元組長度。這個長度和 seq 序列號中位元組數值長度是不一樣的。

現在讓我們學習如何過濾資料包文以便更容易的分析定位問題。

4、過濾封包

正如上面所提,tcpdump 可以抓取很多種型別的資料包文,其中很多可能和我們需要查詢的問題並沒有關係。舉個例子,假設你正在定位一個與 web 伺服器連線的網路問題,就不必關係 SSH 資料包文,因此在抓包結果中過濾掉 SSH 報文可能更便於你分析問題。

tcpdump 有很多引數選項可以設定封包過濾規則,例如根據源 IP 以及目的 IP 地址,埠號,協定等等規則來過濾封包。下面就介紹一些最常用的過濾方法。

協定

在命令中指定協定便可以按照協定型別來篩選封包。比方說用如下命令只要抓取 ICMP 報文:

$ sudo tcpdump -i any -c5 icmptcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes

然後再開啟一個終端,去 ping 另一台機器:

$ ping opensource.comPING opensource.com (54.204.39.132) 56(84) bytes of data.64 bytes from ec2-54-204-39-132.compute-1.amazonaws.com (54.204.39.132): icmp_seq=1 ttl=47 time=39.6 ms

回到執行 tcpdump 命令的終端中,可以看到它篩選出了 ICMP 報文。這裡 tcpdump 並沒有顯示有關 opensource.com 的域名解析封包:

09:34:20.136766 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 1, length 6409:34:20.176402 IP ec2-54-204-39-132.compute-1.amazonaws.com > rhel75: ICMP echo reply, id 20361, seq 1, length 6409:34:21.140230 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 2, length 6409:34:21.180020 IP ec2-54-204-39-132.compute-1.amazonaws.com > rhel75: ICMP echo reply, id 20361, seq 2, length 6409:34:22.141777 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 3, length 645 packets captured5 packets received by filter0 packets dropped by kernel

主機

host 引數只抓取和特定主機相關的封包:

$ sudo tcpdump -i any -c5 -nn host 54.204.39.132tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes09:54:20.042023 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [S], seq 1375157070, win 29200, options [mss 1460,sackOK,TS val 122350391 ecr 0,nop,wscale 7], length 009:54:20.088127 IP 54.204.39.132.80 > 192.168.122.98.39326: Flags [S.], seq 1935542841, ack 1375157071, win 28960, options [mss 1460,sackOK,TS val 522713542 ecr 122350391,nop,wscale 9], length 009:54:20.088204 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 122350437 ecr 522713542], length 009:54:20.088734 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 122350438 ecr 522713542], length 112: HTTP: GET / HTTP/1.109:54:20.129733 IP 54.204.39.132.80 > 192.168.122.98.39326: Flags [.], ack 113, win 57, options [nop,nop,TS val 522713552 ecr 122350438], length 05 packets captured5 packets received by filter0 packets dropped by kernel

如上所示,只抓取和顯示與 54.204.39.132 有關的封包。

埠號

tcpdump 可以根據服務型別或者埠號來篩選封包。例如,抓取和 HTTP 服務相關的封包:

$ sudo tcpdump -i any -c5 -nn port 80tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes09:58:28.790548 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [S], seq 1745665159, win 29200, options [mss 1460,sackOK,TS val 122599140 ecr 0,nop,wscale 7], length 009:58:28.834026 IP 54.204.39.132.80 > 192.168.122.98.39330: Flags [S.], seq 4063583040, ack 1745665160, win 28960, options [mss 1460,sackOK,TS val 522775728 ecr 122599140,nop,wscale 9], length 009:58:28.834093 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 122599183 ecr 522775728], length 009:58:28.834588 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 122599184 ecr 522775728], length 112: HTTP: GET / HTTP/1.109:58:28.878445 IP 54.204.39.132.80 > 192.168.122.98.39330: Flags [.], ack 113, win 57, options [nop,nop,TS val 522775739 ecr 122599184], length 05 packets captured5 packets received by filter0 packets dropped by kernel

IP 地址/主機名

同樣,你也可以根據源 IP 地址或者目的 IP 地址或者主機名來篩選封包。例如抓取源 IP 地址為 192.168.122.98 的封包:

$ sudo tcpdump -i any -c5 -nn src 192.168.122.98tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes10:02:15.220824 IP 192.168.122.98.39436 > 192.168.122.1.53: 59332+ A? opensource.com. (32)10:02:15.220862 IP 192.168.122.98.39436 > 192.168.122.1.53: 20749+ AAAA? opensource.com. (32)10:02:15.364062 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [S], seq 1108640533, win 29200, options [mss 1460,sackOK,TS val 122825713 ecr 0,nop,wscale 7], length 010:02:15.409229 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [.], ack 669337581, win 229, options [nop,nop,TS val 122825758 ecr 522832372], length 010:02:15.409667 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [P.], seq 0:112, ack 1, win 229, options [nop,nop,TS val 122825759 ecr 522832372], length 112: HTTP: GET / HTTP/1.15 packets captured5 packets received by filter0 packets dropped by kernel

注意此處範例中抓取了來自源 IP 地址 192.168.122.98 的 53 埠以及 80 埠的封包,它們的應答包沒有顯示出來因為那些包的源 IP 地址已經變了。

相對的,使用 dst 就是按目的 IP/主機名來篩選封包。

$ sudo tcpdump -i any -c5 -nn dst 192.168.122.98tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes10:05:03.572931 IP 192.168.122.1.53 > 192.168.122.98.47049: 2248 1/0/0 A 54.204.39.132 (48)10:05:03.572944 IP 192.168.122.1.53 > 192.168.122.98.47049: 33770 0/0/0 (32)10:05:03.621833 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [S.], seq 3474204576, ack 3256851264, win 28960, options [mss 1460,sackOK,TS val 522874425 ecr 122993922,nop,wscale 9], length 010:05:03.667767 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [.], ack 113, win 57, options [nop,nop,TS val 522874436 ecr 122993972], length 010:05:03.672221 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 522874437 ecr 122993972], length 642: HTTP: HTTP/1.1 302 Found5 packets captured5 packets received by filter0 packets dropped by kernel

多條件篩選

當然,可以使用多條件組合來篩選封包,使用 and 以及 or 邏輯操作符來建立過濾規則。例如,篩選來自源 IP 地址 192.168.122.98 的 HTTP 封包:

$ sudo tcpdump -i any -c5 -nn src 192.168.122.98 and port 80tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes10:08:00.472696 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [S], seq 2712685325, win 29200, options [mss 1460,sackOK,TS val 123170822 ecr 0,nop,wscale 7], length 010:08:00.516118 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [.], ack 268723504, win 229, options [nop,nop,TS val 123170865 ecr 522918648], length 010:08:00.516583 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [P.], seq 0:112, ack 1, win 229, options [nop,nop,TS val 123170866 ecr 522918648], length 112: HTTP: GET / HTTP/1.110:08:00.567044 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 123170916 ecr 522918661], length 010:08:00.788153 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [F.], seq 112, ack 643, win 239, options [nop,nop,TS val 123171137 ecr 522918661], length 05 packets captured5 packets received by filter0 packets dropped by kernel

你也可以使用括號來建立更為複雜的過濾規則,但在 shell 中請用引號包含你的過濾規則以防止被識別為 shell 表示式:

$ sudo tcpdump -i any -c5 -nn "port 80 and (src 192.168.122.98 or src 54.204.39.132)"tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes10:10:37.602214 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [S], seq 871108679, win 29200, options [mss 1460,sackOK,TS val 123327951 ecr 0,nop,wscale 7], length 010:10:37.650651 IP 54.204.39.132.80 > 192.168.122.98.39346: Flags [S.], seq 854753193, ack 871108680, win 28960, options [mss 1460,sackOK,TS val 522957932 ecr 123327951,nop,wscale 9], length 010:10:37.650708 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 123328000 ecr 522957932], length 010:10:37.651097 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 123328000 ecr 522957932], length 112: HTTP: GET / HTTP/1.110:10:37.692900 IP 54.204.39.132.80 > 192.168.122.98.39346: Flags [.], ack 113, win 57, options [nop,nop,TS val 522957942 ecr 123328000], length 05 packets captured5 packets received by filter0 packets dropped by kernel

該例子中我們只抓取了來自源 IP 為 192.168.122.98 或者 54.204.39.132 的 HTTP (埠號80)的封包。使用該方法就很容易抓取到資料流中互動雙方的封包了。

5、檢查封包內容

在以上的範例中,我們只按封包頭部的資訊來建立規則篩選封包,例如源地址、目的地址、埠號等等。有時我們需要分析網路連線問題,可能需要分析封包中的內容來判斷什麼內容需要被傳送、什麼內容需要被接收等。tcpdump 提供了兩個選項可以檢視封包內容,-X 以十六進位制列印出資料包文內容,-A 列印資料包文的 ASCII 值。

例如,HTTP 請求報文內容如下:

$ sudo tcpdump -i any -c10 -nn -A port 80tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes13:02:14.871803 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [S], seq 2546602048, win 29200, options [mss 1460,sackOK,TS val 133625221 ecr 0,nop,wscale 7], length 0E..<..@[email protected].'[email protected]:02:14.910734 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [S.], seq 1877348646, ack 2546602049, win 28960, options [mss 1460,sackOK,TS val 525532247 ecr 133625221,nop,wscale 9], length 0E..<..@./..a6.'...zb.P..o..&...A..q a...........R.W.......     ................13:02:14.910832 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 133625260 ecr 525532247], length 0E..4..@[email protected].'....P...Ao..'................R.W................13:02:14.911808 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 133625261 ecr 525532247], length 112: HTTP: GET / HTTP/1.1E.....@[email protected].'....P...Ao..'................R.WGET / HTTP/1.1User-Agent: Wget/1.14 (linux-gnu)Accept: */*Host: opensource.comConnection: Keep-Alive................13:02:14.951199 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [.], ack 113, win 57, options [nop,nop,TS val 525532257 ecr 133625261], length 0E..4.F@./.."6.'...zb.P..o..'.......9.2......R.a....................13:02:14.955030 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 525532258 ecr 133625261], length 642: HTTP: HTTP/1.1 302 FoundE....G@./...6.'...zb.P..o..'.......9........R.b....HTTP/1.1 302 FoundServer: nginxDate: Sun, 23 Sep 2018 17:02:14 GMTContent-Type: text/html; charset=iso-8859-1Content-Length: 207X-Content-Type-Options: nosniffLocation: https://opensource.com/Cache-Control: max-age=1209600Expires: Sun, 07 Oct 2018 17:02:14 GMTX-Request-ID: v-6baa3acc-bf52-11e8-9195-22000ab8cf2dX-Varnish: 632951979Age: 0Via: 1.1 varnish (Varnish/5.2)X-Cache: MISSConnection: keep-alive<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>302 Found</title></head><body><h1>Found</h1><p>The document has moved <a href="https://opensource.com/">here</a>.</p></body></html>................13:02:14.955083 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 133625304 ecr 525532258], length 0E..4..@[email protected].'....P....o...................R.b................13:02:15.195524 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [F.], seq 113, ack 643, win 239, options [nop,nop,TS val 133625545 ecr 525532258], length 0E..4..@[email protected].'....P....o...................R.b................13:02:15.236592 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 525532329 ecr 133625545], length 0E..4.H@./.. 6.'...zb.P..o..........9.I......R......................13:02:15.236656 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 644, win 239, options [nop,nop,TS val 133625586 ecr 525532329], length 0E..4..@[email protected].'....P....o...................R..................10 packets captured10 packets received by filter0 packets dropped by kernel

這對定位一些普通 HTTP 呼叫 API 介面的問題很有用。當然如果是加密報文,這個輸出也就沒多大用了。

6、儲存抓包資料

tcpdump 提供了儲存抓包資料的功能以便後續分析封包。例如,你可以夜裡讓它在那裡抓包,然後早上起來再去分析它。同樣當有很多封包時,顯示過快也不利於分析,將封包儲存下來,更有利於分析問題。

使用 -w 選項來儲存封包而不是在螢幕上顯示出抓取的封包:

$ sudo tcpdump -i any -c10 -nn -w webserver.pcap port 80[sudo] password for ricardo:tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes10 packets captured10 packets received by filter0 packets dropped by kernel

該命令將抓取的封包儲存到檔案 webserver.pcap。字尾名 pcap 表示檔案是抓取的封包格式。

正如範例中所示,儲存封包到檔案中時螢幕上就沒有任何有關資料包文的輸出,其中 -c10 表示抓取到 10 個封包後就停止抓包。如果想有一些反饋來提示確實抓取到了封包,可以使用 -v 選項。

tcpdump 將封包儲存在二進位制檔案中,所以不能簡單的用文字編輯器去開啟它。使用 -r 選項引數來閱讀該檔案中的報文內容:

$ tcpdump -nn -r webserver.pcapreading from file webserver.pcap, link-type LINUX_SLL (Linux cooked)13:36:57.679494 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [S], seq 3709732619, win 29200, options [mss 1460,sackOK,TS val 135708029 ecr 0,nop,wscale 7], length 013:36:57.718932 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [S.], seq 1999298316, ack 3709732620, win 28960, options [mss 1460,sackOK,TS val 526052949 ecr 135708029,nop,wscale 9], length 013:36:57.719005 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 135708068 ecr 526052949], length 013:36:57.719186 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 135708068 ecr 526052949], length 112: HTTP: GET / HTTP/1.113:36:57.756979 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [.], ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 013:36:57.760122 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 642: HTTP: HTTP/1.1 302 Found13:36:57.760182 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 135708109 ecr 526052959], length 013:36:57.977602 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [F.], seq 113, ack 643, win 239, options [nop,nop,TS val 135708327 ecr 526052959], length 013:36:58.022089 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 526053025 ecr 135708327], length 013:36:58.022132 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 644, win 239, options [nop,nop,TS val 135708371 ecr 526053025], length 0$

這裡不需要管理員許可權 sudo 了,因為此刻並不是在網路介面處抓包。

你還可以使用我們討論過的任何過濾規則來過濾檔案中的內容,就像使用實時資料一樣。 例如,通過執行以下命令從源 IP 地址 54.204.39.132 檢查檔案中的封包:

$ tcpdump -nn -r webserver.pcap src 54.204.39.132reading from file webserver.pcap, link-type LINUX_SLL (Linux cooked)13:36:57.718932 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [S.], seq 1999298316, ack 3709732620, win 28960, options [mss 1460,sackOK,TS val 526052949 ecr 135708029,nop,wscale 9], length 013:36:57.756979 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [.], ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 013:36:57.760122 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 642: HTTP: HTTP/1.1 302 Found13:36:58.022089 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 526053025 ecr 135708327], length 0

下一步做什麼?

以上的基本功能已經可以幫助你使用強大的 tcpdump 抓包工具了。更多的內容請參考 tcpdump 網站 以及它的 幫助檔案

tcpdump 命令列工具為分析網路流量封包提供了強大的靈活性。如果需要使用圖形工具來抓包請參考 Wireshark

Wireshark 還可以用來讀取 tcpdump 儲存的 pcap 檔案。你可以使用 tcpdump 命令列在沒有 GUI 介面的遠端機器上抓包然後在 Wireshark 中分析封包。