一、簡介
tcpdump就是:dump the traffic on a network,根據使用者的定義對網絡上的數據包進行截獲的包分析工具。
tcpdump是一個用于截取網絡分組,并輸出分組內容的工具。憑借強大的功能和靈活的截取策略,使其成為類UNIX系統下用于網絡分析和問題排查的首選工具
tcpdump 支持針對網絡層、協議、主機、網絡或端口的過濾,并提供and、or、not等邏輯語句來幫助你去掉無用的信息
tcpdump需要有root權限。
tcpdump使用了獨立于系統的libpcap的接口。libpcap是linux平臺下的網絡數據包捕獲函數包
tcpdump調用libpcap的接口在linux系統鏈路層抓包。而linux本身指定的許多訪問控制規則都是基于三層或三層以上的過濾規則,所以tcpdump可以抓取過濾規則之前的數據包。
tcpdump可以使用帶-w參數的tcpdump 截獲數據并保存到文件中,然后再使用Wireshark進行解碼分析
tcpdump工作在網卡的混雜模式
二、使用
1、命令格式
tcpdump [-aAbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ][ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ][ -i interface ] [ -j tstamptype ] [ -M secret ] [ --number ][ -Q in|out|inout ][ -r file ] [ -s snaplen ] [ --time-stamp-precision precision ][ --immediate-mode ] [ -T type ] [ --version ] [ -V file ][ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ][ -Z user ] [ expression ]
2、命令選項
①抓包選項
-A
: 以ASCII碼方式顯示每一個數據包(不會顯示數據包中鏈路層頭部信息). 在抓取包含網頁數據的數據包時, 可方便查看數據(nt: 即Handy for capturing web pages).
-C file-size
: (nt: 此選項用于配合-w file 選項使用) 該選項使得tcpdump 在把原始數據包直接保存到文件中之前, 檢查此文件大小是否超過file-size. 如果超過了, 將關閉此文件,另創一個文件繼續用于原始數據包的記錄. 新創建的文件名與-w 選項指定的文件名一致, 但文件名后多了一個數字.該數字會從1開始隨著新創建文件的增多而增加. file-size的單位是百萬字節(nt: 這里指1,000,000個字節,并非1,048,576個字節, 后者是以1024字節為1k, 1024k字節為1M計算所得, 即1M=1024 * 1024 = 1,048,576)
-c
:指定要抓取的包數量。
-d
?: 以容易閱讀的形式,在標準輸出上打印出編排過的包匹配碼, 隨后tcpdump停止.(nt | rt: human readable, 容易閱讀的,通常是指以ascii碼來打印一些信息. compiled, 編排過的. packet-matching code, 包匹配碼,含義未知, 需補充)
-dd
: 以C語言的形式打印出包匹配碼.
-ddd
: 以十進制數的形式打印出包匹配碼(會在包匹配碼之前有一個附加的'count'前綴).
-i interface
:指定tcpdump需要監聽的接口。默認會抓取第一個網絡接口
-N
: 不列出域名
-n
:對地址以數字方式顯式,否則顯式為主機名,也就是說-n選項不做主機名解析。
-nn
:除了-n的作用外,還把端口顯示為數值,否則顯示端口服務名。
-P
:指定要抓取的包是流入還是流出的包。可以給定的值為in、out和inout
,默認為"inout"。
-p
: 不讓網絡界面進入混雜模式
-O
: 不將數據包編碼最佳化
-s len
:設置tcpdump的數據包抓取長度為len。
? 如果不設置默認將會是65535字節。對于要抓取的數據包較大時,長度設置不夠可能會產生包截斷,若出現包截斷,輸出行中會出現"[|proto]"的標志(proto實際會顯示為協議名)。但是抓取len越長,包的處理時間越長,并且會減少tcpdump可緩存的數據包的數量,從而會導致數據包的丟失,所以在能抓取我們想要的包的前提下,抓取長度越小越好。
-S
: 打印TCP 數據包的順序號時, 使用絕對的順序號, 而不是相對的順序號.
? 相對順序號可理解為, 相對第一個TCP 包順序號的差距,比如, 接受方收到第一個數據包的絕對順序號為232323, 對于后來接收到的第2個,第3個數據包, tcpdump會打印其序列號為1, 2分別表示與第一個數據包的差距為1 和 2. 而如果此時-S 選項被設置, 對于后來接收到的第2個, 第3個數據包會打印出其絕對順序號:232324, 232325
-y datalinktype
:設置tcpdump 只捕獲數據鏈路層協議類型是datalinktype的數據包
②輸出選項
-e
:輸出的每行中都將包括數據鏈路層頭部信息,例如源MAC和目標MAC。
-q
:快速打印輸出。即打印很少的協議相關信息,從而輸出行都比較簡短。
-t
:在每行輸出中不打印時間戳
-tt
:不對每行輸出的時間進行格式處理(nt: 這種格式一眼可能看不出其含義, 如時間戳打印成1261798315)
-ttt
:tcpdump 輸出時, 每兩行打印之間會延遲一個段時間(以毫秒為單位)
-tttt
:在每行打印的時間戳之前添加日期的打印
-X
:輸出包的頭部數據,會以16進制和ASCII兩種方式同時輸出。
-XX
:輸出包的頭部數據,會以16進制和ASCII兩種方式同時輸出,更詳細。
-v
:當分析和打印的時候,產生詳細的輸出。
-vv
:產生比-v更詳細的輸出。
-vvv
:產生比-vv更詳細的輸出。
③其他功能性選項
-D
:列出可用于抓包的接口。將會列出接口的數值編號和接口名,它們都可以用于"-i"
后。
-F
:從文件中讀取抓包的表達式。若使用該選項,則命令行中給定的其他表達式都將失效。
-w
:將抓包數據輸出到文件中而不是標準輸出。可以同時配合”-G time"選項使得輸出文件每time秒就自動切換到另一個文件。可通過"-r"選項載入這些文件以進行分析和打印。
-r
:從給定的數據包文件中讀取數據。使用"-"表示從標準輸入中讀取
3、條件表達式定義過濾規則
表達式用于決定哪些數據包將被過濾打印. 如果不給定條件表達式, 網絡上所有被捕獲的包都會被打印,否則, 只有滿足條件表達式的數據包被打印
表達式格式:
tcpdump 命令選項 proto dir type
-
proto(protocol協議類型的過濾器):根據協議進行過濾
- tcp:
- udp:
- icmp:
- ether:
- fddi:
- tr:
- wlan:
- ip:
- ip6:
- arp:
- rarp:
- decnet:
- 若未給定協議類型,則匹配所有可能的類型
-
dir(direction數據流向類型的過濾器):根據數據流向進行過濾
- src:
- dst:
- src or dst:
- src and dst:
-
type(關鍵詞類型的過濾器)
:- host:
-
net:
- port:
- portrange:
- ether:
- gateway:
例如:host 192.168.201.128 , net 128.3, port 20, portrange 6000-6008’
4、過濾規則的組合
表達式單元之間可以使用操作符" and / && / or / || / not / ! "
進行連接,從而組成復雜的條件表達式。
and
:所有的條件都需要滿足,也可以表示為?&&
or
:只要有一個條件滿足就可以,也可以表示為?||
not
:取反,也可以使用?!
而在單個過濾器里,常常會判斷一條件是否成立,這時候,就要使用下面兩個符號
=
:判斷二者相等==
:判斷二者相等!=
:判斷二者不相等
使用括號"()"可以改變表達式的優先級,但需要注意的是括號會被shell解釋,所以應該使用反斜線""轉義為"()",在需要的時候,還需要包圍在引號中。
當你使用這兩個符號時,tcpdump 還提供了一些關鍵字的接口來方便我們進行判斷,比如
if
:表示網卡接口名proc
:表示進程名pid
:表示進程idsvc
:表示 service classdir
:表示方向,in 和 outeproc
:表示 effective process nameepid
:表示 effective process ID
三、抓包解讀
輸出格式
$ tcpdump -S -e -nn -i eth0 dst 192.168.1.7 and port 500006:24:16.887580 dc:a6:32:c4:88:d2 > 00:11:32:11:22:33, ethertype IPv4 (0x0800), length 338: 192.168.1.18.54832 > 192.168.1.7.5000: Flags [P.], seq 2391754816:2391755088, ack 1379501343, win 2051, options [nop,nop,TS val 238444658 ecr 19745762], length 272
-
第一列:時分秒毫秒 21:26:49.013621
-
第二列:源MAC地址
-
第三列:目標MAC地址
-
第四列:網絡協議及其長度
-
第五列:源IP地址.端口號
-
第六列:目標IP地址.端口號
-
第七列:數據包內容,包括Flags 標識符,seq 號,ack 號,win 窗口,數據長度 length,其中 [P.] 表示 PUSH 標志位為 1,
Flags 標識符
- [S]?: SYN(發起連接標志)
- [P]?: PSH(傳送數據標志)
- [F]?: FIN (關閉連接標志)
- [R]?: RST(重置連接)
- [.]?: 沒有 Flag,由于除了 SYN 包外所有的數據包都有ACK,所以一般這個標志也可表示 ACK
組合表示
- [S.]: SYN同步標識,以及確認S的ACK
- [P.]: 推送數據, 和 ACK
- [R.]: RST, 連接重置
- [F.]: FIN 結束連接
- [DF]: Don't Fragment(不要碎裂),當DF=0時,表示允許分片,一般-v時才有這個標識
- [FP.]: 標記FIN、PUSH、ACK組合,這樣做是為了提升網絡效率,減少數據來回確認等
四、示例
1、監聽多個端口、多個網卡
# 監聽多個端口
tcpdump port 22 or port 23 or port 24 # 監聽所有網卡
tcpdump -i any port 22 or port 23
2、找出一段時間內發包數最多的 IP
$ tcpdump -nnn -t -c 200 | cut -f 1,2,3,4 -d '.' | sort | uniq -c | sort -nr | head -n 20200 packets captured
244 packets received by filter
0 packets dropped by kernel103 IP 192.168.1.1872 IP 220.64.11.9225 IP 192.168.1.7
3、抓取 HTTP GET 請求
$ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'$ tcpdump -vv -A -l -i6 | grep 'GET'
4、抓取 HTTP POST請求
$ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'$ tcpdump -vv -A -l -i6 | grep 'POST'
5、抓取 HTTP請求中的 User-Agent和Host
$ tcpdump -nn -A -i6 -l | egrep -i 'User-Agent:|Host:'
6、抓取 HTTP請求中的主機名和路徑
$ tcpdump -i6 -v -n -l | egrep -i "POST /|GET /|Host:".Ke..B]'POST /webapi/entry.cgi HTTP/1.1
Host: 192.168.1.7:5000
7、抓取 HTTP 有效數據包
抓取 80 端口的 HTTP 有效數據包,排除 TCP 連接建立過程的數據包(SYN / FIN / ACK)
$ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'