Linux tcpdump 使用介紹

本文分享自微信公眾號 - 高效能伺服器開發(transfer_3561453275),作者:張小方

Linux tcpdump 使用介紹

tcpdump

是 Linux 系統提供一個非常強大的抓包工具,熟練使用它,對我們排查網路問題非常有用。如果你的機器上還沒有安裝,可以使用如下命令安裝:

yum install tcpdump

如果要使用

tcpdump

命令必須具有

sudo

許可權。

tcpdump

常用的選項有:

-i

指定要捕獲的目標網絡卡名,網絡卡名可以使用前面章節中介紹的

ifconfig

命令獲得;如果要抓所有網絡卡的上的包,可以使用

any

關鍵字。 ## 抓取網絡卡ens33上的包 tcpdump -i ens33 ## 抓取所有網絡卡上的包 tcpdump -i any

-X

以 ASCII 和十六進位制的形式輸出捕獲的資料包內容,減去鏈路層的包頭資訊;

-XX

以 ASCII 和十六進位制的形式輸出捕獲的資料包內容,包括鏈路層的包頭資訊。

-n

不要將 ip 地址顯示成別名的形式;

-nn

不要將 ip 地址和埠以別名的形式顯示。

-S

以絕對值顯示包的 ISN 號(包序列號),預設以上一包的偏移量顯示。

-vv

抓包的資訊詳細地顯示;

-vvv

抓包的資訊更詳細地顯示。

-w

將抓取的包的原始資訊(不解析,也不輸出)寫入檔案中,後跟檔名: tcpdump -i any -w filename

-r

從利用

-w

選項儲存的包檔案中讀取資料包資訊。

除了可以使用選項以外,

tcpdump

還支援各種資料包過濾的表示式,常見的形式如下:

## 僅顯示經過埠 8888 上的資料包(包括tcp:8888和udp:8888)tcpdump -i any ‘port 8888’## 僅顯示經過埠是 tcp:8888 上的資料包tcpdump -i any ‘tcp port 8888’## 僅顯示從源埠是 tcp:8888 的資料包tcpdump -i any ‘tcp src port 8888’## 僅顯示源埠是 tcp:8888 或目標埠是 udp:9999 的包 tcpdump -i any ‘tcp src port 8888 or udp dst port 9999’## 僅顯示地址是127。0。0。1 且源埠是 tcp:9999 的包 ,以 ASCII 和十六進位制顯示詳細輸出,## 不顯示 ip 地址和埠號的別名tcpdump -i any ‘src host 127。0。0。1 and tcp src port 9999’ -XX -nn -vv

下面我們透過三個具體的操作例項來演示一下使用

tcpdump

的抓包過程。

例項一 :連線一個正常的偵聽埠

假設我的伺服器端的地址是

127.0.0.0.1:12345

,使用 nc 命令在一個 shell 視窗建立一個伺服器程式並在這個地址上進行偵聽。

nc –v -l 127。0。0。0。112345

效果如下圖所示:

Linux tcpdump 使用介紹

在另外一個 shell 視窗開啟 tcpdump 抓包:

tcpdump -i any ‘port 12345’ -XX -nn -vv

效果如下:

Linux tcpdump 使用介紹

然後再開一個 shell 視窗,利用 nc 命令建立一個客戶端去連線伺服器:

nc -v 127。0。0。1 12345

Linux tcpdump 使用介紹

我們抓到的包如下:

Linux tcpdump 使用介紹

由於我們沒有在客戶端和伺服器之間傳送任何訊息,其實抓到的包就是 TCP 連線的三次握手資料包,分析如下:

三次握手過程是客戶端先給伺服器傳送一個

SYN

,然後伺服器應答一個

SYN + ACK

,應答的序列號是遞增

1

的,表示應答哪個請求,即從

4004096087

遞增到

4004096088

,接著客戶端再應答一個

ACK

。這個時候,我們發現發包序列號和應答序列號都變成

1

了,這是 tcpdump 使用相對序號,我們加上

-S

選項後就變成絕對序列號了。

我們按 Ctrl + C 中斷 tcpdump 抓包過程,並停止用 nc 開啟的客戶端和伺服器程式,然後在前面的 tcpdump 命令後面加上

-S

選項重新開啟抓包,使用命令如下:

tcpdump -i any ‘port 12345’ -XX -nn -vv -S

然後再按順序用 nc 命令再次啟動下伺服器和客戶端程式。再次得到抓包結果:

Linux tcpdump 使用介紹

這次得到的包的序號就是絕對序號了。

例項二:連線一個不存在的偵聽埠

例項一

演示的是正常的 TCP 連線三次握手過程捕獲到的資料包。假如我們連線的

伺服器 ip 地址存在

,但

監聽埠號不存在

,我們看下 tcpdump 抓包結果。除了在一個 shell 視窗啟動一個 tcpdump 抓包監測,在另外一個 shell 視窗用 nc 命令去連線一個不存在的偵聽埠即可。

Linux tcpdump 使用介紹

抓包資料如下:

Linux tcpdump 使用介紹

這個時候客戶端傳送

SYN

,伺服器應答

ACK+RST

,這個應答包會導致客戶端的 connect 連線失敗返回。

例項三:連線一個很遙遠的 ip,或者網路繁忙的情形

實際情形中,還存在一種情況就是客戶端訪問一個很遙遠的 ip,或者網路繁忙,伺服器對客戶端傳送的 TCP 三次握手的網路 SYN 報文沒有應答,會出現什麼情況呢?

我們透過設定防火牆規則來模擬一下這種情況。使用

iptables -F

先將防火牆的已有規則都清理掉,然後給防火牆的 INPUT 鏈上增加一個規則:丟棄本地網絡卡 lo(也就是 127。0。0。1 這個迴環地址)上的所有 SYN 包。

iptables -Fiptables -I INPUT -p tcp ——syn -i lo -j DROP

Linux tcpdump 使用介紹

如果讀者對 CentOS 的防火牆 iptables 命令有興趣,可以使用 man iptables 在 man 手冊中檢視更詳細的幫助。

在開啟 tcpdump 抓包之後和設定防火牆規則之後,利用 nc 命令去連線 127。0。0。1:12345 這個地址。整個過程操作效果圖如下:

Linux tcpdump 使用介紹

接著,我們得到 tcpdump 抓到的資料包如下:

Linux tcpdump 使用介紹