簡(jiǎn)單介紹
tcpdump 是一款強(qiáng)大的網(wǎng)絡(luò)抓包工具靴跛,運(yùn)行在 linux 平臺(tái)上。熟悉 tcpdump 的使用能夠幫助你分析丑念、調(diào)試網(wǎng)絡(luò)數(shù)據(jù)巴比。
要想使用很好地掌握 tcpdump, 必須對(duì)網(wǎng)絡(luò)報(bào)文(TCP/IP 協(xié)議)有一定的了解。不過(guò)對(duì)于簡(jiǎn)單的使用來(lái)說(shuō),只要有網(wǎng)絡(luò)基礎(chǔ)概念就行了。
tcpdump 是一個(gè)很復(fù)雜的命令狈茉,想了解它的方方面面非常不易,也不值得推薦掸掸,能夠使用它解決日常工作中的問(wèn)題才是關(guān)鍵氯庆。
選項(xiàng)
tcpdump 的選項(xiàng)也很多,要想知道所有選項(xiàng)的話扰付,請(qǐng)參考 man tcpdump
堤撵,下面只記錄 tcpdump 最常用的選項(xiàng)。
完整的英文文檔:https://www.tcpdump.org/tcpdump_man.html
需要注意的是羽莺,tcpdump 默認(rèn)只會(huì)截取前 96 字節(jié)的內(nèi)容实昨,要想截取所有的報(bào)文內(nèi)容,可以使用 -s number
盐固, number
就是你要截取的報(bào)文字節(jié)數(shù)荒给,如果是 0 的話丈挟,表示截取報(bào)文全部?jī)?nèi)容。
-
-n
表示不要解析域名志电,直接顯示 ip曙咽。 -
-nn
不要解析域名和端口 -
-X
同時(shí)用 hex 和 ascii 顯示報(bào)文的內(nèi)容。 -
-XX
同-X
溪北,但同時(shí)顯示以太網(wǎng)頭部桐绒。 -
-S
顯示絕對(duì)的序列號(hào)(sequence number)夺脾,而不是相對(duì)編號(hào)之拨。 -
-i any
監(jiān)聽(tīng)所有的網(wǎng)卡 -
-v, -vv, -vvv
:顯示更多的詳細(xì)信息 -
-c number
: 截取 number 個(gè)報(bào)文,然后結(jié)束 -
-A
: 只使用 ascii 打印報(bào)文的全部數(shù)據(jù)咧叭,不要和-X
一起使用蚀乔。截取 http 請(qǐng)求的時(shí)候可以用sudo tcpdump -nSA port 80!
以太網(wǎng)幀的封包格式為:
Frame = Ethernet Header + IP Header + TCP Header + TCP Segment Data
-
Ethernet Header
=14 Byte =Dst Physical Address(6 Byte)+ Src Physical Address(6 Byte)+Type(2 Byte)菲茬,以太網(wǎng)幀頭以下稱之為數(shù)據(jù)幀吉挣。 -
IP Header
=20 Byte(without options field),數(shù)據(jù)在IP層稱為Datagram婉弹,分片稱為Fragment睬魂。 -
TCP Header
= 20 Byte(without options field),數(shù)據(jù)在TCP層稱為Stream镀赌,分段稱為Segment(UDP中稱為Message)氯哮。 - 54個(gè)字節(jié)后為TCP數(shù)據(jù)負(fù)載部分(Data Portion),即應(yīng)用層用戶數(shù)據(jù)商佛。
Ethernet Header
以下的IP數(shù)據(jù)報(bào)最大傳輸單位為MTU
(Maximum Transmission Unit喉钢,Effect of short board),對(duì)于大多數(shù)使用以太網(wǎng)的局域網(wǎng)來(lái)說(shuō)良姆,MTU=1500
肠虽。
TCP數(shù)據(jù)包每次能夠傳輸?shù)淖畲髷?shù)據(jù)分段為MSS,為了達(dá)到最佳的傳輸效能玛追,在建立TCP連接時(shí)雙方將協(xié)商MSS值——雙方提供的MSS值中的最小值為這次連接的最大MSS值税课。MSS往往基于MTU計(jì)算出來(lái),通常MSS
=MTU-sizeof(IP Header)-sizeof(TCP Header)=1500-20-20=1460痊剖。
這樣韩玩,數(shù)據(jù)經(jīng)過(guò)本地TCP層分段后,交給本地IP層邢笙,在本地IP層就不需要分片了啸如。但是在下一跳路由(Next Hop)的鄰居路由器上可能發(fā)生IP分片!因?yàn)槁酚善鞯木W(wǎng)卡的MTU可能小于需要轉(zhuǎn)發(fā)的IP數(shù)據(jù)報(bào)的大小氮惯。
這時(shí)候叮雳,在路由器上可能發(fā)生兩種情況:
(1)如果源發(fā)送端設(shè)置了這個(gè)IP數(shù)據(jù)包可以分片(May Fragment想暗,DF=0),路由器將IP數(shù)據(jù)報(bào)分片后轉(zhuǎn)發(fā)帘不。
(2)如果源發(fā)送端設(shè)置了這個(gè)IP數(shù)據(jù)報(bào)不可以分片(Don’t Fragment说莫,DF=1),路由器將IP數(shù)據(jù)報(bào)丟棄寞焙,并發(fā)送ICMP分片錯(cuò)誤消息給源發(fā)送端储狭。
簡(jiǎn)單使用(實(shí)例)
tcpdump -vv
默認(rèn)啟動(dòng),普通情況下捣郊,直接啟動(dòng)tcpdump將監(jiān)視第一個(gè)網(wǎng)絡(luò)接口上所有流過(guò)的數(shù)據(jù)包
tcpdump -nS
監(jiān)聽(tīng)所有端口辽狈,直接顯示 ip 地址。
tcpdump -nnvvS
顯示更詳細(xì)的數(shù)據(jù)報(bào)文呛牲,包括 tos, ttl, checksum 等刮萌。
tcpdump -nnvvXS
顯示數(shù)據(jù)報(bào)的全部數(shù)據(jù)信息,用 hex 和 ascii 兩列對(duì)比輸出娘扩。
下面是抓取 ping 命令的請(qǐng)求和返回的兩個(gè)報(bào)文着茸,可以看到全部的數(shù)據(jù)。
? ~ sudo tcpdump -nnvXSs 0 -c2 icmp
tcpdump: data link type PKTAP
tcpdump: listening on pktap, link-type PKTAP (Packet Tap), capture size 65535 bytes
22:58:16.781856 IP (tos 0x0, ttl 64, id 61452, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.106 > 192.168.1.1: ICMP echo request, id 65302, seq 0, length 64
0x0000: 0c72 2c28 b9ac 80e6 5019 4c38 0800 4500 .r,(....P.L8..E.
0x0010: 0054 f00c 0000 4001 06e1 c0a8 016a c0a8 .T....@......j..
0x0020: 0101 0800 72c9 ff16 0000 5500 5808 000b ....r.....U.X...
0x0030: ee08 0809 0a0b 0c0d 0e0f 1011 1213 1415 ................
0x0040: 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 ...........!"#$%
0x0050: 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 &'()*+,-./012345
0x0060: 3637 67
22:58:17.674304 IP (tos 0x0, ttl 64, id 13972, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.1 > 192.168.1.106: ICMP echo reply, id 65302, seq 0, length 64
0x0000: 80e6 5019 4c38 0c72 2c28 b9ac 0800 4500 ..P.L8.r,(....E.
0x0010: 0054 3694 0000 4001 c059 c0a8 0101 c0a8 .T6...@..Y......
0x0020: 016a 0000 7ac9 ff16 0000 5500 5808 000b .j..z.....U.X...
0x0030: ee08 0809 0a0b 0c0d 0e0f 1011 1213 1415 ................
0x0040: 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 ...........!"#$%
0x0050: 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 &'()*+,-./012345
0x0060: 3637 67
2 packets captured
5875 packets received by filter
0 packets dropped by kernel
過(guò)濾器
機(jī)器上的網(wǎng)絡(luò)報(bào)文數(shù)量異常的多琐旁,很多時(shí)候我們只關(guān)系和具體問(wèn)題有關(guān)的數(shù)據(jù)報(bào)(比如訪問(wèn)某個(gè)網(wǎng)站的數(shù)據(jù)涮阔,或者 icmp 超時(shí)的報(bào)文等等),而這些數(shù)據(jù)只占到很小的一部分灰殴。把所有的數(shù)據(jù)截取下來(lái)敬特,從里面找到想要的信息無(wú)疑是一件很費(fèi)時(shí)費(fèi)力的工作。而 tcpdump 提供了靈活的語(yǔ)法可以精確地截取關(guān)心的數(shù)據(jù)報(bào)验懊,簡(jiǎn)化分析的工作量擅羞。這些選擇數(shù)據(jù)包的語(yǔ)句就是過(guò)濾器(filter)!
過(guò)濾器也可以簡(jiǎn)單地分為三類:type
, dir
和 proto
义图。
Type
讓你區(qū)分報(bào)文的類型减俏,主要由 host
(主機(jī)), net
(網(wǎng)絡(luò)) 和 port
(端口) 組成。src
和 dst
也可以用來(lái)過(guò)濾報(bào)文的源地址和目的地址碱工。
host: 過(guò)濾某個(gè)主機(jī)的數(shù)據(jù)報(bào)文
tcpdump host 1.2.3.4
src, dst: 過(guò)濾源地址和目的地址
tcpdump src 2.3.4.5
tcpdump dst 3.4.5.6
net: 過(guò)濾某個(gè)網(wǎng)段的數(shù)據(jù)娃承,CIDR 模式
tcpdump net 1.2.3.0/24
proto: 過(guò)濾某個(gè)協(xié)議的數(shù)據(jù),支持 tcp, udp 和 icmp怕篷。使用的時(shí)候可以省略 proto 關(guān)鍵字历筝。
tcpdump icmp
port: 過(guò)濾通過(guò)某個(gè)端口的數(shù)據(jù)報(bào)
tcpdump port 3389
src/dst, port, protocol: 結(jié)合三者
tcpdump src port 1025 and tcp
tcpdump udp and src port 53
此外還有指定端口和數(shù)據(jù)報(bào)文范圍的過(guò)濾器:
port 范圍
tcpdump portrange 21-23
數(shù)據(jù)報(bào)大小,單位是字節(jié)
tcpdump less 32
tcpdump greater 128
tcpdump > 32
tcpdump <= 128
過(guò)于過(guò)濾器的更多詳細(xì)信息廊谓,請(qǐng)?jiān)L問(wèn) tcpdump 官方 map page 的 PCAP-FILTER 部分
輸出到文件
使用 tcpdump 截取數(shù)據(jù)報(bào)文的時(shí)候梳猪,默認(rèn)會(huì)打印到屏幕的默認(rèn)輸出,你會(huì)看到按照順序和格式蒸痹,很多的數(shù)據(jù)一行行快速閃過(guò)春弥,根本來(lái)不及看清楚所有的內(nèi)容呛哟。不過(guò),tcpdump 提供了把截取的數(shù)據(jù)保存到文件的功能匿沛,以便后面使用其他圖形工具(比如 wireshark扫责,Snort)來(lái)分析。
-w
選項(xiàng)用來(lái)把數(shù)據(jù)報(bào)文輸出到文件逃呼,比如下面的命令就是把所有 80 端口的數(shù)據(jù)導(dǎo)入到文件
# sudo tcpdump -w capture_file.pcap port 80
-r
可以讀取文件里的數(shù)據(jù)報(bào)文鳖孤,顯示到屏幕上。
# tcpdump -nXr capture_file.pcap host web30
NOTE:保存到文件的數(shù)據(jù)不是屏幕上看到的文件信息抡笼,而是包含了額外信息的固定格式 pcap苏揣,需要特殊的軟件(如:Wireshark
)來(lái)查看,使用 vim 或者 cat 命令會(huì)出現(xiàn)亂碼蔫缸。
強(qiáng)大的過(guò)濾器
過(guò)濾的真正強(qiáng)大之處在于你可以隨意組合它們腿准,而連接它們的邏輯就是常用的 與/AND/&&
、 或/OR/||
和 非/not/!
拾碌。
源地址是 10.5.2.3,目的端口是 3389 的數(shù)據(jù)報(bào)
tcpdump -nnvS src 10.5.2.3 and dst port 3389
從 192.168 網(wǎng)段到 10 或者 172.16 網(wǎng)段的數(shù)據(jù)報(bào)
tcpdump -nvX src net 192.168.0.0/16 and dat net 10.0.0.0/8 or 172.16.0.0/16
從 Mars 或者 Pluto 發(fā)出的數(shù)據(jù)報(bào)街望,并且目的端口不是 22
tcpdump -vv src mars or pluto and not dat port 22
從上面的例子就可以看出校翔,你可以隨意地組合之前的過(guò)濾器來(lái)截取自己期望的數(shù)據(jù)報(bào),最重要的就是知道自己要精確匹配的數(shù)據(jù)室怎樣的灾前!
對(duì)于比較復(fù)雜的過(guò)濾器表達(dá)式防症,為了邏輯的清晰,可以使用括號(hào)哎甲。不過(guò)默認(rèn)情況下蔫敲,tcpdump 把 ()
當(dāng)做特殊的字符,所以必須使用單引號(hào) '
來(lái)消除歧義:
tcpdump -nvv -c 20 'src 10.0.2.4 and (dat port 3389 or 22)'
實(shí)例一
tcpdump -i eth1 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))'
抓取所有經(jīng)過(guò)eth1炭玫,目的地址是192.168.1.254或192.168.1.200端口是80的TCP數(shù)
實(shí)例二
tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))'
抓取所有經(jīng)過(guò)eth1奈嘿,目標(biāo)MAC地址是00:01:02:03:04:05的ICMP數(shù)據(jù)
實(shí)例三
tcpdump -i eth1 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))'
抓取所有經(jīng)過(guò)eth1,目的網(wǎng)絡(luò)是192.168吞加,但目的主機(jī)不是192.168.1.200的TCP數(shù)據(jù)
理解 tcpdump 的輸出
截取數(shù)據(jù)只是第一步裙犹,第二步就是理解這些數(shù)據(jù),下面就解釋一下 tcpdump 命令輸出各部分的意義衔憨。
21:27:06.995846 IP (tos 0x0, ttl 64, id 45646, offset 0, flags [DF], proto TCP (6), length 64)
192.168.1.106.56166 > 124.192.132.54.80: Flags [S], cksum 0xa730 (correct), seq 992042666, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 663433143 ecr 0,sackOK,eol], length 0
21:27:07.030487 IP (tos 0x0, ttl 51, id 0, offset 0, flags [DF], proto TCP (6), length 44)
124.192.132.54.80 > 192.168.1.106.56166: Flags [S.], cksum 0xedc0 (correct), seq 2147006684, ack 992042667, win 14600, options [mss 1440], length 0
21:27:07.030527 IP (tos 0x0, ttl 64, id 59119, offset 0, flags [DF], proto TCP (6), length 40)
192.168.1.106.56166 > 124.192.132.54.80: Flags [.], cksum 0x3e72 (correct), ack 2147006685, win 65535, length 0
最基本也是最重要的信息就是數(shù)據(jù)報(bào)的源地址/端口和目的地址/端口叶圃,上面的例子第一條數(shù)據(jù)報(bào)中,源地址 ip 是 192.168.1.106
践图,源端口是 56166
掺冠,目的地址是 124.192.132.54
,目的端口是 80
码党。 >
符號(hào)代表數(shù)據(jù)的方向德崭。
此外悍及,上面的三條數(shù)據(jù)還是 tcp 協(xié)議的三次握手過(guò)程,第一條就是 SYN
報(bào)文接癌,這個(gè)可以通過(guò) Flags [S]
看出心赶。下面是常見(jiàn)的 TCP 報(bào)文的 Flags:
-
[S]
: SYN(開(kāi)始連接) -
[.]
: 沒(méi)有 Flag -
[P]
: PSH(推送數(shù)據(jù)) -
[F]
: FIN (結(jié)束連接) -
[R]
: RST(重置連接)
而第二條數(shù)據(jù)的 [S.]
表示 SYN-ACK
,就是 SYN
報(bào)文的應(yīng)答報(bào)文缺猛。
比較常用的方式
如果是為了查看數(shù)據(jù)內(nèi)容缨叫,建議用tcpdump -s 0 -w filename
把數(shù)據(jù)包都保存下來(lái),然后用wireshark的Follow TCP Stream/Follow UDP Stream來(lái)查看整個(gè)會(huì)話的內(nèi)容荔燎。-s 0
是抓取完整數(shù)據(jù)包耻姥,否則默認(rèn)只抓68字節(jié)。用tcpflow也可以方便的獲取TCP會(huì)話內(nèi)容有咨,支持tcpdump的各種表達(dá)式琐簇。
UDP頭
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source | Destination |
| Port | Port |
+--------+--------+--------+--------+
| | |
| Length | Checksum |
+--------+--------+--------+--------+
| |
| DATA ... |
+-----------------------------------+
/*UDP頭定義,共8個(gè)字節(jié)*/
typedef struct _UDP_HEADER
{
unsigned short m_usSourPort; //源端口號(hào)16bit
unsigned short m_usDestPort; //目的端口號(hào)16bit
unsigned short m_usLength; //數(shù)據(jù)包長(zhǎng)度16bit
unsigned short m_usCheckSum; //校驗(yàn)和16bit
}__attribute__((packed))UDP_HEADER, *PUDP_HEADER;
- 抓DNS請(qǐng)求數(shù)據(jù)
tcpdump -i eth1 udp dst port 53
系統(tǒng)測(cè)試
-c
參數(shù)對(duì)于運(yùn)維人員來(lái)說(shuō)也比較常用座享,因?yàn)榱髁勘容^大的服務(wù)器婉商,靠人工CTRL+C還是抓的太多,甚至導(dǎo)致服務(wù)器宕機(jī)渣叛,于是可以用-c
參數(shù)指定抓多少個(gè)包丈秩。
time tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn' -c 10000 > /dev/null
上面的命令計(jì)算抓10000個(gè)SYN包花費(fèi)多少時(shí)間,可以判斷訪問(wèn)量大概是多少淳衙。
tcpdump 與wireshark
Wireshark(以前是ethereal)是Windows下非常簡(jiǎn)單易用的抓包工具蘑秽。但在Linux下很難找到一個(gè)好用的圖形化抓包工具。
還好有Tcpdump箫攀。我們可以用Tcpdump + Wireshark 的完美組合實(shí)現(xiàn):在 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這些選項(xiàng)等都要放到第一個(gè)參數(shù)的位置,用來(lái)過(guò)濾數(shù)據(jù)報(bào)的類型 -
-i eth1
: 只抓經(jīng)過(guò)接口eth1的包 -
-t
: 不顯示時(shí)間戳 -
-s 0
: 抓取數(shù)據(jù)包時(shí)默認(rèn)抓取長(zhǎng)度為68字節(jié)汤求。加上-S 0 后可以抓到完整的數(shù)據(jù)包 -
-c 100
: 只抓取100個(gè)數(shù)據(jù)包 -
dst port ! 22
: 不抓取目標(biāo)端口是22的數(shù)據(jù)包 -
src net 192.168.1.0/24
: 數(shù)據(jù)包的源網(wǎng)絡(luò)地址為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"前兩個(gè)字母"GE"
0x4854
為"HTTP"前兩個(gè)字母"HT"
tcpdump 對(duì)截獲的數(shù)據(jù)并沒(méi)有進(jìn)行徹底解碼,數(shù)據(jù)包內(nèi)的大部分內(nèi)容是使用十六進(jìn)制的形式直接打印輸出的扬绪。顯然這不利于分析網(wǎng)絡(luò)故障竖独,通常的解決辦法是先使用帶-w
參數(shù)的tcpdump 截獲數(shù)據(jù)并保存到文件中,然后再使用其他程序(如Wireshark
)進(jìn)行解碼分析挤牛。當(dāng)然也應(yīng)該定義過(guò)濾規(guī)則莹痢,以避免捕獲的數(shù)據(jù)包填滿整個(gè)硬盤。
基本上tcpdump總的的輸出格式為:系統(tǒng)時(shí)間 來(lái)源主機(jī).端口 > 目標(biāo)主機(jī).端口 數(shù)據(jù)包參數(shù)