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

1、簡述html

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

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;
一、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:從給定的數據包文件中讀取數據。使用"-"表示從標準輸入中讀取。 

經常使用選項有如下幾個:web

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

二、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關鍵字。shell

若是咱們只須要列出送到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' ,'||';這些關鍵字能夠組合起來構成強大的組合條件來知足人們的須要,下面舉幾個例子來講明。express

三、tcpdump 表達式vim

表達式用於篩選輸出哪些類型的數據包,若是沒有給定表達式,全部的數據包都將輸出,不然只輸出表達式爲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"windows

 

除了使用修飾符和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解釋,因此應該使用反斜線"\"轉義爲"\(\)",在須要的時候,還須要包圍在引號中。緩存

 2、tcpdump 具體使用方法安全

一、普通狀況下,直接啓動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

3、tcpdump 實踐經驗

 一、查看DNS解析狀況

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

1.一、命令:tcpdump -n -i any port 53

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

1.二、命令: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.一、命令:tcpdump -i eth0 -c 10 -w data.pcap

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

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

4、高級過濾方式

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

proto[x:y]          : 過濾從x字節開始的y字節數。好比ip[2:2]過濾出三、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

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

一、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的整數倍。

二、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'

三、分片標記

當發送端的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.一、匹配MF,分片包

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

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

4.二、匹配分片和最後分片

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

測試分片能夠用下面的命令:  

ping -M want -s 3000 192.168.1.1

五、匹配小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'

六、抓大於X字節的包  

a.大於600字節  

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

七、更多的過濾方式  

首先仍是須要知道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.一、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'

九、抓SMTP數據  

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

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

十、抓HTTP GET數據

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

"GET "的十六進制是47455420  

十一、抓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)'

5、比較經常使用的方式 

若是是爲了查看數據內容,建議用tcpdump -s 0 -w filename把數據包都保存下來,而後用wireshark的Follow TCP Stream/Follow UDP Stream來查看整個會話的內容。-s 0是抓取完整數據包,不然默認只抓68字節。用tcpflow也能夠方便的獲取TCP會話內容,支持tcpdump的各類表達式。 

一、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 

二、系統測試

 -c參數對於運維人員來講也比較經常使用,由於流量比較大的服務器,靠人工CTRL+C仍是抓的太多,甚至致使服務器宕機,因而能夠用-c參數指定抓多少個包。

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

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

三、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)分析

四、使用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總的的輸出格式爲:系統時間 來源主機.端口 > 目標主機.端口 數據包參數

  

---------------------------------------------書山有路勤爲徑,學海無涯苦做舟-------------------------------------------------------- 

參考資料

http://www.javashuo.com/article/p-nmnazlzy-cd.html

相關文章
相關標籤/搜索