Linux系統診斷必備技能之二:tcpdump抓包工具詳解


一、簡述

TcpDump可以將網絡中傳送的數據包完全截獲下來提供分析。它支持針對網絡層、協議、主機、網絡或端口的過濾,並提供and、or、not等邏輯語句來幫助你去掉無用的信息。

Linux作為網絡服務器,特別是作為路由器和網關時,數據的采集和分析是不可少的。TcpDump是Linux中強大的網絡數據采集分析工具之一。
用簡單的話來定義tcpdump,就是:dump the traffic on a network,根據使用者的定義對網絡上的 數據包進行截獲的包分析工具。
作為互聯網上經典的的系統管理員必備工具,tcpdump以其強大的功能,靈活的截取策略,成為每個高級的系統管理員分析網絡,排查問題等所必備的工具之一。
tcpdump提供了源代碼,公開了接口,因此具備很強的可擴展性,對於網絡維護和入侵者都是非常有用的工具。tcpdump存在於基本的 FreeBSD系統中,由於它需要將網絡接口設置為混雜模式,普通用戶不能正常執行,但具備root權限的用戶可以直接執行它來獲取網絡上的信息。因此系統中存在網絡分析工具主要不是對本機安全的威脅,而是對網絡上的其他計算機的安全存在威脅。
基本上tcpdump的總的輸出格式為:系統時間 來源主機.端口 > 目標主機.端口 數據包參數
完整的英文文檔:https://www.tcpdump.org/tcpdump_man.html
tcpdump官網:http://www.tcpdump.org/
This is the official web site of tcpdump, a powerful command-line packet analyzer;
1、tcpdump命令格式
tcpdump [ -DenNqvX ] [ -c count ] [ -F file ] [ -i interface ] [ -r file ]
        [ -s snaplen ] [ -w file ] [ expression ]

抓包選項:
-c:指定要抓取的包數量。注意,是最終要獲取這么多個包。例如,指定"-c 10"將獲取10個包,但可能已經處理了100個包,只不過只有10個包是滿足條件的包。
-i interface:指定tcpdump需要監聽的接口。若未指定該選項,將從系統接口列表中搜尋編號最小的已配置好的接口(不包括loopback接口,要抓取loopback接口使用tcpdump -i lo),
            :一旦找到第一個符合條件的接口,搜尋馬上結束。可以使用'any'關鍵字表示所有網絡接口。
-n:對地址以數字方式顯式,否則顯式為主機名,也就是說-n選項不做主機名解析。
-nn:除了-n的作用外,還把端口顯示為數值,否則顯示端口服務名。
-N:不打印出host的域名部分。例如tcpdump將會打印'nic'而不是'nic.ddn.mil'。
-P:指定要抓取的包是流入還是流出的包。可以給定的值為"in"、"out"和"inout",默認為"inout"。
-s len:設置tcpdump的數據包抓取長度為len,如果不設置默認將會是65535字節。對於要抓取的數據包較大時,長度設置不夠可能會產生包截斷,若出現包截斷,
      :輸出行中會出現"[|proto]"的標志(proto實際會顯示為協議名)。但是抓取len越長,包的處理時間越長,並且會減少tcpdump可緩存的數據包的數量,
      :從而會導致數據包的丟失,所以在能抓取我們想要的包的前提下,抓取長度越小越好。

輸出選項:
-e:輸出的每行中都將包括數據鏈路層頭部信息,例如源MAC和目標MAC。
-q:快速打印輸出。即打印很少的協議相關信息,從而輸出行都比較簡短。
-X:輸出包的頭部數據,會以16進制和ASCII兩種方式同時輸出。
-XX:輸出包的頭部數據,會以16進制和ASCII兩種方式同時輸出,更詳細。
-v:當分析和打印的時候,產生詳細的輸出。
-vv:產生比-v更詳細的輸出。
-vvv:產生比-vv更詳細的輸出。

其他功能性選項:
-D:列出可用於抓包的接口。將會列出接口的數值編號和接口名,它們都可以用於"-i"后。
-F:從文件中讀取抓包的表達式。若使用該選項,則命令行中給定的其他表達式都將失效。
-w:將抓包數據輸出到文件中而不是標准輸出。可以同時配合"-G time"選項使得輸出文件每time秒就自動切換到另一個文件。可通過"-r"選項載入這些文件以進行分析和打印。
-r:從給定的數據包文件中讀取數據。使用"-"表示從標准輸入中讀取。 

常用選項有以下幾個:

a.tcpdump -D
b.tcpdump -c num -i int -nn -XX -vvv

2、tcpdump 幾種關鍵字說明

第一種是關於類型的關鍵字,主要包括host,net,port, 例如 host 210.27.48.2,指明 210.27.48.2是一台主機,net 202.0.0.0 指明 202.0.0.0是一個網絡地址,port 23 指明端口號是23。如果沒有指定類型,缺省的類型是host.
第二種是確定傳輸方向的關鍵字,主要包括src , dst ,dst or src, dst and src ,這些關鍵字指明了傳輸的方向。舉例說明,src 210.27.48.2 ,指明ip包中源地址是210.27.48.2 , dst net 202.0.0.0 指明目的網絡地址是202.0.0.0 。如果沒有指明方向關鍵字,則缺省是src or dst關鍵字。

如果我們只需要列出送到80端口的數據包,用dst port;如果我們只希望看到返回80端口的數據包,用src port。 
#tcpdump –i eth0 host hostname and dst port 80  目的端口是80
或者
#tcpdump –i eth0 host hostname and src port 80  源端口是80  一般是提供http的服務的主機
如果條件很多的話  要在條件之前加and 或 or 或 not
#tcpdump -i eth0 host ! 211.161.223.70 and ! 211.161.223.71 and dst port 80
如果在ethernet 使用混雜模式 系統的日志將會記錄
May  7 20:03:46 localhost kernel: eth0: Promiscuous mode enabled.
May  7 20:03:46 localhost kernel: device eth0 entered promiscuous mode
May  7 20:03:57 localhost kernel: device eth0 left promiscuous mode
tcpdump對截獲的數據並沒有進行徹底解碼,數據包內的大部分內容是使用十六進制的形式直接打印輸出的。顯然這不利於分析網絡故障,通常的解決辦法是先使用帶-w參數的tcpdump 截獲數據並保存到文件中,然后再使用其他程序進行解碼分析。當然也應該定義過濾規則,以避免捕獲的數據包填滿整個硬盤。

第三種是協議的關鍵字,主要包括fddi,ip,arp,rarp,tcp,udp等類型。Fddi指明是在FDDI(分布式光纖數據接口網絡)上的特定 的網絡協議,實際上它是"ether"的別名,fddi和ether具有類似的源地址和目的地址,所以可以將fddi協議包當作ether的包進行處理和 分析。其他的幾個關鍵字就是指明了監聽的包的協議內容。如果沒有指定任何協議,則tcpdump將會監聽所有協議的信息包。
除了這三種類型的關鍵字之外,其他重要的關鍵字如下:gateway, broadcast,less,greater,還有三種邏輯運算,取非運算是 'not ' '! ', 與運算是'and','&&;或運算 是'or' ,'||';這些關鍵字可以組合起來構成強大的組合條件來滿足人們的需要,下面舉幾個例子來說明。

3、tcpdump 表達式

表達式用於篩選輸出哪些類型的數據包,如果沒有給定表達式,所有的數據包都將輸出,否則只輸出表達式為true的包。在表達式中出現的shell元字符建議使用單引號包圍。
tcpdump的表達式由一個或多個"單元"組成,每個單元一般包含ID的修飾符和一個ID(數字或名稱)。有三種修飾符:
(1).type:指定ID的類型。
可以給定的值有host/net/port/portrange。例如"host foo","net 128.3","port 20","portrange 6000-6008"。默認的type為host。
(2).dir:指定ID的方向。
可以給定的值包括src/dst/src or dst/src and dst,默認為src or dst。例如,"src foo"表示源主機為foo的數據包,"dst net 128.3"表示目標網絡為128.3的數據包,"src or dst port 22"表示源或目的端口為22的數據包。
(3).proto:通過給定協議限定匹配的數據包類型。
常用的協議有tcp/udp/arp/ip/ether/icmp等,若未給定協議類型,則匹配所有可能的類型。例如"tcp port 21","udp portrange 7000-7009"。
所以,一個基本的表達式單元格式為"proto dir type ID"

 

除了使用修飾符和ID組成的表達式單元,還有上述2小節中提到的關鍵字表達式單元:gateway,broadcast,less,greater以及算術表達式。
表達式單元之間可以使用操作符" and / && / or / || / not / ! "進行連接,從而組成復雜的條件表達式。如"host foo and not port ftp and not port ftp-data",這表示篩選的數據包要滿足"主機為foo且端口不是ftp(端口21)和ftp-data(端口20)的包",常用端口和名字的對應關系可在linux系統中的/etc/service文件中找到。
另外,同樣的修飾符可省略,如"tcp dst port ftp or ftp-data or domain"與"tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain"意義相同,都表示包的協議為tcp且目的端口為ftp或ftp-data或domain(端口53)。
使用括號"()"可以改變表達式的優先級,但需要注意的是括號會被shell解釋,所以應該使用反斜線"\"轉義為"\(\)",在需要的時候,還需要包圍在引號中。

 二、tcpdump 具體使用方法

1、普通情況下,直接啟動tcpdump將監視第一個網絡界面上所有流過的數據包。

常用使用方法有:

A想要截獲所有210.27.48.1 的主機收到的和發出的所有的數據包:
#tcpdump host 210.27.48.1

B想要截獲主機210.27.48.1 和主機210.27.48.2 或210.27.48.3的通信,使用命令:(在命令行中適用 括號時,一定要
#tcpdump host 210.27.48.1 and / (210.27.48.2 or 210.27.48.3 /)

C如果想要獲取主機210.27.48.1除了和主機210.27.48.2之外所有主機通信的ip包,使用命令:
#tcpdump ip host 210.27.48.1 and ! 210.27.48.2

D如果想要獲取主機210.27.48.1接收或發出的telnet包,使用如下命令:
#tcpdump tcp port 23 host 210.27.48.1

E 對本機的udp 123 端口進行監視 123 為ntp的服務端口
# tcpdump udp port 123

F 系統將只對名為hostname的主機的通信數據包進行監視。主機名可以是本地主機,也可以是網絡上的任何一台計算機。下面的命令可以讀取主機hostname發送的所有數據: 
#tcpdump -i eth0 src host hostname

G 下面的命令可以監視所有送到主機hostname的數據包: 
#tcpdump -i eth0 dst host hostname

H  我們還可以監視通過指定網關的數據包: 
#tcpdump -i eth0 gateway Gatewayname

I 如果你還想監視編址到指定端口的TCP或UDP數據包,那么執行以下命令: 
#tcpdump -i eth0 host hostname and port 80

J 如果想要獲取主機210.27.48.1除了和主機210.27.48.2之外所有主機通信的ip包
,使用命令:
#tcpdump ip host 210.27.48.1 and ! 210.27.48.2

K 想要截獲主機210.27.48.1 和主機210.27.48.2 或210.27.48.3的通信,使用命令
:(在命令行中適用 括號時,一定要
#tcpdump host 210.27.48.1 and / (210.27.48.2 or 210.27.48.3 /)

L 如果想要獲取主機210.27.48.1除了和主機210.27.48.2之外所有主機通信的ip包,使用命令:
 #tcpdump ip host 210.27.48.1 and ! 210.27.48.2

M 如果想要獲取主機210.27.48.1接收或發出的telnet包,使用如下命令:
 #tcpdump tcp port 23 host 210.27.48.1

三、tcpdump 實踐經驗

 1、查看DNS解析情況

Linux系統要想正常訪問互聯網,需要正確配置DNS解析,現在我們已經配置公司內部DNS,我們想看一下DNS解析是否正常,就可以使用tcpdump來抓取DNS包,准備好兩個xshell
窗口,按照如下方式操作:

1.1、命令:tcpdump -n -i any port 53

盡量在root用戶下使用tcpdump命令,-n表示不要把IP地址解析成域名,-i表示抓取哪塊網卡的通信數據包,any表示任意一塊,port是指定要抓取數據包的端口,DNS服務工作在53端口上,執行完畢之后,我們切換到第2個窗口,進行下一步;

1.2、命令:ping -c10 baidu.com

 注解:-c10表示和ping次停下,這時候我們的計算機和百度產生的通信,窗口1的tcpdump就會監聽到我們的通信數據,也就是所謂的抓包,切換到窗口1,看到的數據大致如下:

在上圖中我們可看到本地172.16.50.96,端口52892進程向公司本地DNS服務器 172.16.51.151請求告知baidu.com的IP地址是什么?DNS服務器成功給了我們答復,由此可以說明,我們的DNS工作
正常。

2、抓取主機指定網卡的數據包

2.1、命令:tcpdump -i eth0 -c 10 -w data.pcap

說明:-i 指定要抓取數據包的網卡名稱
          -c 指定抓取包的個數;
          -w 保存到指定文件

注意:可以看到,我們保存的my-packets.pcap是一種特殊文件,直接使用vim是無法查看的,可以把
該文件拿到windows下,使用wireshark查看;

四、高級過濾方式

首先了解如何從包頭過濾信息

proto[x:y]          : 過濾從x字節開始的y字節數。比如ip[2:2]過濾出3、4字節(第一字節從0開始排)
proto[x:y] & z = 0  : proto[x:y]和z的與操作為0
proto[x:y] & z !=0  : proto[x:y]和z的與操作不為0
proto[x:y] & z = z  : proto[x:y]和z的與操作為z
proto[x:y] = z      : proto[x:y]等於z

操作符 : >, <, >=, <=, =, !=

1、IP頭(IPV4)

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |Type of Service|          Total Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Identification        |Flags|      Fragment Offset    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live |    Protocol   |         Header Checksum       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Source Address                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Destination Address                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    | <-- optional
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            DATA ...                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

中文:

/*IP頭定義,共20個字節*/
typedef struct _IP_HEADER
{
 char m_cVersionAndHeaderLen;       //版本信息(前4位),頭長度(后4位)
 char m_cTypeOfService;            // 服務類型8位
 short m_sTotalLenOfPacket;        //數據包長度
 short m_sPacketID;              //數據包標識
 short m_sSliceinfo;               //分片使用
 char m_cTTL;                  //存活時間
 char m_cTypeOfProtocol;          //協議類型
 short m_sCheckSum;             //校驗和
 unsigned int m_uiSourIp;          //源ip
 unsigned int m_uiDestIp;          //目的ip
} __attribute__((packed))IP_HEADER, *PIP_HEADER ;

a.版本:指IP協議的版本,通信雙方使用的IP協議版本必須一致。一般的值為0100(IPv4),0110(IPv6)。
b.首部長度:長度4比特。這個字段的作用是為了描述IP包頭的長度,因為在IP包頭中有變長的可選部分。該部分占4個bit位,單位為32bit(4個字節),即本區域值=IP頭部長度(單位為bit)/(8*4,因此,一個IP包頭的長度最長為“1111”,即15*4=60個字節。IP包頭最小長度為20字節。
c.優先級與服務類型:長度8比特,定義了數據包傳輸的緊急程度以及時延、可靠性、傳輸成本等。
d.總長度:16比特,以字節為單位描述IP包的總長度(包括頭部和數據兩部分),最大值為65535。第二行中標識符、標志和段偏移量通常聯合使用,用於數據拆分時的分組和重組。
e.標識符:對於上層發來的較大的數據包,往往需要拆分。路由器將一個大包進行拆分后,拆出來的所有部分被標上相同的值,該值即為標識符,用於告訴目的端哪些包屬於同一個大包。
f.標志:長度3比特。該字段第一位不使用。第二位是DF(Don't Fragment)位,DF位設為1時表明路由器不能對該上層數據包分段。如果一個上層數據包無法在不分段的情況下進行轉發,則路由器會丟棄該上層數據包並返回一個錯誤信息。第三位是MF(More Fragments)位,當路由器對一個上層數據包分段,則路由器會在除了最后一個分段的IP包的包頭中將MF位設為1。
g.段偏移量:長度13比特,表示一個數據包在原先被拆分前的大包中的位置。接收端據此來還原和組裝IP包。
h.TTL:表示IP包的生存時間,長度8比特。長度8比特。當IP包進行傳送時,先會對該字段賦予某個特定的值。當IP包經過每一個沿途的路由器的時候,每個沿途的路由器會將IP包的TTL值減少1。如果TTL減少為0,則該IP包會被丟棄。這個字段可以防止由於路由環路而導致IP包在網絡中不停被轉發。
i.協議號:長度8比特,標識上一層即傳輸層在本次數據傳輸中所使用的協議。比如6代表TCP,17代表UDP等
j.首部校驗和:長度16位。用來做IP頭部的正確性檢測,但不包含數據部分。 因為每個路由器要改變TTL的值,所以路由器會為每個通過的數據包重新計算這個值。
k.源地址:長度32比特,標識IP包的起源地址。
l.目標地址:長度32比特,表示IP包的目的地址。
m.可選項:可變長字段,主要用於測試,由起源設備跟據需要改寫。
n.填充:因為IP包頭長度(Header Length)部分的單位為32bit,所以IP包頭的長度必須為32bit的整數倍。因此,在可選項后面,IP協議會填充若干個0,以達到32bit的整數倍。

2、IP選項

“一般”的IP頭是20字節,但IP頭有選項設置,不能直接從偏移21字節處讀取數據。IP頭有個長度字段可以知道頭長度是否大於20字節。
通常第一個字節的二進制值是:01000101,分成兩個部分:
0100 = 4 表示IP版本 0101 = 5 表示IP頭32 bit的塊數,5 x 32 bits = 160 bits or 20 bytes
如果第一字節第二部分的值大於5,那么表示頭有IP選項。
下面介紹有過濾方法
0100 0101 : 第一字節的二進制
0000 1111 : 與操作
<=========
0000 0101 : 結果

正確的過濾方法:

tcpdump -i eth1 'ip[0] & 15 > 5'
或
tcpdump -i eth1 'ip[0] & 0x0f > 5'

3、分片標記

當發送端的MTU大於到目的路徑鏈路上的MTU時就會被分片,分片信息在IP頭的第七和第八字節:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bit 0: 保留,必須是0
Bit 1: (DF) 0 = 可能分片, 1 = 不分片
Bit 2: (MF) 0 = 最后的分片, 1 = 還有分片
Fragment Offset字段只有在分片的時候才使用。
要抓帶DF位標記的不分片的包,第七字節的值應該是:
01000000 = 64

tcpdump -i eth1 'ip[6] = 64'

4、抓分片包  

4.1、匹配MF,分片包

tcpdump -i eth1 'ip[6] = 32'

最后分片包的開始3位是0,但是有Fragment Offset字段。

4.2、匹配分片和最后分片

tcpdump -i eth1 '((ip[6:2] > 0) and (not ip[6] = 64))'

測試分片可以用下面的命令:  

ping -M want -s 3000 192.168.1.1

5、匹配小TTL

TTL字段在第九字節,並且正好是完整的一個字節,TTL最大值是255,二進制為11111111。
可以用下面的命令驗證一下:

$ ping -M want -s 3000 -t 256 192.168.1.200
ping: ttl 256 out of range
 +-+-+-+-+-+-+-+-+
 | Time to Live | +-+-+-+-+-+-+-+-+

a.在網關可以用下面的命令看看網絡中誰在使用traceroute  

tcpdump -i eth1 'ip[8] < 5'

6、抓大於X字節的包  

a.大於600字節  

tcpdump -i eth1 'ip[2:2] > 600'

7、更多的過濾方式  

首先還是需要知道TCP基本結構  

a.TCP頭

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |       |C|E|U|A|P|R|S|F|                               |
| Offset|  Res. |W|C|R|C|S|S|Y|I|            Window             |
|       |       |R|E|G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

/*TCP頭定義,共20個字節*/
typedef struct _TCP_HEADER
{
 short m_sSourPort;              // 源端口號16bit
 short m_sDestPort;              // 目的端口號16bit
 unsigned int m_uiSequNum;         // 序列號32bit
 unsigned int m_uiAcknowledgeNum;  // 確認號32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP頭長度;中6位:保留;后6位:標志位
 short m_sWindowSize;            // 窗口大小16bit
 short m_sCheckSum;              // 檢驗和16bit
 short m_surgentPointer;           // 緊急數據偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
/*TCP頭中的選項定義
 
kind(8bit)+Length(8bit,整個選項的長度,包含前兩部分)+內容(如果有的話)
 
KIND =
  1表示 無操作NOP,無后面的部分
 
  2表示 maximum segment   后面的LENGTH就是maximum segment選項的長度(以byte為單位,1+1+內容部分長度)
 
  3表示 windows scale     后面的LENGTH就是 windows scale選項的長度(以byte為單位,1+1+內容部分長度)
 
  4表示 SACK permitted    LENGTH為2,沒有內容部分
 
  5表示這是一個SACK包     LENGTH為2,沒有內容部分
 
  8表示時間戳,LENGTH為10,含8個字節的時間戳
*/
16位源端口號和16位目的端口號。
32位序號:一次TCP通信過程中某一個傳輸方向上的字節流的每個字節的編號,通過這個來確認發送的數據有序,比如現在序列號為1000,發送了1000,下一個序列號就是2000。
32位確認號:用來響應TCP報文段,給收到的TCP報文段的序號加1,三握時還要攜帶自己的序號。
4位頭部長度:標識該TCP頭部有多少個4字節,共表示最長15*4=60字節。同IP頭部。
6位保留。6位標志。URG(緊急指針是否有效)ACK(表示確認號是否有效)PSH(提示接收端應用程序應該立即從TCP接收緩沖區讀走數據)RST(表示要求對方重新建立連接)SYN(表示請求建立一個連接)FIN(表示通知對方本端要關閉連接)
16位窗口大小:TCP流量控制的一個手段,用來告訴對端TCP緩沖區還能容納多少字節。
16位校驗和:由發送端填充,接收端對報文段執行CRC算法以檢驗TCP報文段在傳輸中是否損壞。
16位緊急指針:一個正的偏移量,它和序號段的值相加表示最后一個緊急數據的下一字節的序號。
標志位字段(U、A、P、R、S、F):占6比特。各比特的含義如下:

URG:緊急指針(urgent pointer)有效。
ACK:確認序號有效。
PSH:接收方應該盡快將這個報文段交給應用層。
RST:重建連接。
SYN:發起一個連接。
FIN:釋放一個連接。
窗口大小字段:占16比特。此字段用來進行流量控制。單位為字節數,這個值是本機期望一次接收的字節數。
TCP校驗和字段:占16比特。對整個TCP報文段,即TCP頭部和TCP數據進行校驗和計算,並由目標端進行驗證。
緊急指針字段:占16比特。它是一個偏移量,和序號字段中的值相加表示緊急數據最后一個字節的序號。
選項字段:占32比特。可能包括"窗口擴大因子"、"時間戳"等選項。  

a.抓取源端口大於1024的TCP數據包

tcpdump -i eth1 'tcp[0:2] > 1024'

匹配TCP數據包的特殊標記  

TCP標記定義在TCP頭的第十四個字節
+-+-+-+-+-+-+-+-+
|C|E|U|A|P|R|S|F|
|W|C|R|C|S|S|Y|I|
|R|E|G|K|H|T|N|N|
+-+-+-+-+-+-+-+-+
只抓SYN包,第十四字節是二進制的00000010,也就是十進制的2

tcpdump -i eth1 'tcp[13] = 2'
抓SYN, ACK (00010010 or 18)
tcpdump -i eth1 'tcp[13] = 18'
抓SYN或者SYN-ACK
tcpdump -i eth1 'tcp[13] & 2 = 2'
抓PSH-ACK
tcpdump -i eth1 'tcp[13] = 24'
抓所有包含FIN標記的包(FIN通常和ACK一起,表示幽會完了,回見)
tcpdump -i eth1 'tcp[13] & 1 = 1'
抓RST
tcpdump -i eth1 'tcp[13] & 4 = 4'

8、常用的字段偏移名字

8.1、tcpdump考慮了一些數字恐懼症者的需求,提供了部分常用的字段偏移名字:

a.icmptype (ICMP類型字段)
b.icmpcode (ICMP符號字段)
c.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-push, tcp-ack, tcp-urg
這樣上面按照TCP標記位抓包的就可以寫直觀的表達式了:

a.只抓SYN包  

tcpdump -i eth1 'tcp[tcpflags] = tcp-syn'  

b.抓SYN、ACK  

tcpdump -i eth1 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'

9、抓SMTP數據  

tcpdump -i eth1 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'

抓取數據區開始為"MAIL"的包,"MAIL"的十六進制為0x4d41494c。  

10、抓HTTP GET數據

tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x47455420'

"GET "的十六進制是47455420  

11、抓SSH返回 

tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x5353482D'

"SSH-"的十六進制是0x5353482D  

tcpdump -i eth1 '(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)'

五、比較常用的方式 

如果是為了查看數據內容,建議用tcpdump -s 0 -w filename把數據包都保存下來,然后用wireshark的Follow TCP Stream/Follow UDP Stream來查看整個會話的內容。-s 0是抓取完整數據包,否則默認只抓68字節。用tcpflow也可以方便的獲取TCP會話內容,支持tcpdump的各種表達式。 

1、UDP頭

0      7 8 15 16 23 24 31 +--------+--------+--------+--------+ | Source | Destination | | Port | Port | +--------+--------+--------+--------+ | | | | Length | Checksum | +--------+--------+--------+--------+ | | | DATA ... | +-----------------------------------+
/*UDP頭定義,共8個字節*/
 
typedef struct _UDP_HEADER
{
 unsigned short m_usSourPort;       // 源端口號16bit
 unsigned short m_usDestPort;       // 目的端口號16bit
 unsigned short m_usLength;        // 數據包長度16bit
 unsigned short m_usCheckSum;      // 校驗和16bit
}__attribute__((packed))UDP_HEADER, *PUDP_HEADER;

a.抓DNS請求數據 

tcpdump -i eth1 udp dst port 53 

2、系統測試

 -c參數對於運維人員來說也比較常用,因為流量比較大的服務器,靠人工CTRL+C還是抓的太多,甚至導致服務器宕機,於是可以用-c參數指定抓多少個包。

time tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn' -c 10000 > /dev/null

上面的命令計算抓10000個SYN包花費多少時間,可以判斷訪問量大概是多少。  

3、tcpdump 與 wireshark

Wireshark(以前是ethereal)是Windows下非常簡單易用的抓包工具。但在Linux下很難找到一個好用的圖形化抓包工具。
還好有Tcpdump。我們可以用Tcpdump + Wireshark 的完美組合實現:在 Linux 里抓包,然后在Windows 里分析包。

tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
tcp: ip icmp arp rarp 和 tcp、udp、icmp這些選項等都要放到第一個參數的位置,用來過濾數據報的類型
-i eth1 : 只抓經過接口eth1的包
-t : 不顯示時間戳
-s 0 : 抓取數據包時默認抓取長度為68字節。加上-S 0 后可以抓到完整的數據包
-c 100 : 只抓取100個數據包
dst port ! 22 : 不抓取目標端口是22的數據包
src net 192.168.1.0/24 : 數據包的源網絡地址為192.168.1.0/24
-w ./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析

4、使用tcpdump 抓取HTTP包

tcpdump  -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854

0x4745 為"GET"前兩個字母"GE",0x4854 為"HTTP"前兩個字母"HT"。
tcpdump 對截獲的數據並沒有進行徹底解碼,數據包內的大部分內容是使用十六進制的形式直接打印輸出的。顯然這不利於分析網絡故障,通常的解決辦法是先使用帶-w參數的tcpdump 截獲數據並保存到文件中,然后再使用其他程序(如Wireshark)進行解碼分析。當然也應該定義過濾規則,以避免捕獲的數據包填滿整個硬盤。
基本上tcpdump總的的輸出格式為:系統時間 來源主機.端口 > 目標主機.端口 數據包參數

  

---------------------------------------------書山有路勤為徑,學海無涯苦作舟-------------------------------------------------------- 

參考資料

https://www.cnblogs.com/chenpingzhao/p/9108570.html

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM