肝了三天,萬字長文教你玩轉(zhuǎn) tcpdump,從此抓包不用愁

來自公眾號(hào):Python編程時(shí)光
鏈接:http://python.iswbm.com/en/latest/c10/c10_04.html

今天要給大家介紹的一個(gè) Unix 下的一個(gè) 網(wǎng)絡(luò)數(shù)據(jù)采集分析工具 ****--**** Tcpdump撼短,也就是我們常說的抓包工具。

與它功能類似的工具有 wireshark 挺勿,不同的是曲横,wireshark 有圖形化界面,而 tcpdump 則只有命令行不瓶。

由于我本人更習(xí)慣使用命令行的方式進(jìn)行抓包禾嫉,因此今天先跳過 wireshark,直接給大家介紹這個(gè) tcpdump 神器蚊丐。

這篇文章熙参,我肝了好幾天,借助于Linux 的 man 幫助命令麦备,我把 tcpdump 的用法全部研究了個(gè)遍孽椰,才形成了本文。

不夸張的說凛篙,應(yīng)該可以算是中文里把 tcpdump 講得最清楚明白黍匾,并且最全的文章了(至少我從百度、谷歌的情況來看是這樣)呛梆,所以本文值得你收藏分享锐涯,就怕你錯(cuò)過了,就再也找不到像這樣把 tcpdump 講得直白而且特全的文章了填物。

在講解之前纹腌,有兩點(diǎn)需要聲明:

  1. 第三節(jié)到第六節(jié)里的 tcpdump 命令示例霎终,只為了說明參數(shù)的使用,并不一定就能抓到包升薯,如果要精準(zhǔn)抓到你所需要的包莱褒,需要配合第五節(jié)的邏輯邏輯運(yùn)算符進(jìn)行組合搭配。

  2. 不同 Linux 發(fā)行版下覆劈、不同版本的 tcpdump 可能有小許差異保礼, 本文是基于 CentOS 7.2 的 4.5.1 版本的tcpdump 進(jìn)行學(xué)習(xí)的,若在你的環(huán)境中無法使用责语,請(qǐng)參考 man tcpdump 進(jìn)行針對(duì)性學(xué)習(xí)炮障。

1. tcpdump 核心參數(shù)圖解

大家都知道,網(wǎng)絡(luò)上的流量坤候、數(shù)據(jù)包胁赢,非常的多,因此要想抓到我們所需要的數(shù)據(jù)包白筹,就需要我們定義一個(gè)精準(zhǔn)的過濾器智末,把這些目標(biāo)數(shù)據(jù)包,從巨大的數(shù)據(jù)包網(wǎng)絡(luò)中抓取出來徒河。

所以學(xué)習(xí)抓包工具系馆,其實(shí)就是學(xué)習(xí)如何定義過濾器的過程。

而在 tcpdump 的世界里顽照,過濾器的實(shí)現(xiàn)由蘑,都是通過一個(gè)又一個(gè)的參數(shù)組合起來,一個(gè)參數(shù)不夠精準(zhǔn)代兵,那就再加一個(gè)尼酿,直到我們能過濾掉無用的數(shù)據(jù)包,只留下我們感興趣的數(shù)據(jù)包植影。

tcpdump 的參數(shù)非常的多裳擎,初學(xué)者在沒有掌握 tcpdump 時(shí),會(huì)對(duì)這個(gè)命令的眾多參數(shù)產(chǎn)生很多的疑惑思币。

就比如下面這個(gè)命令鹿响,我們要通過 host 參數(shù)指定 host ip 進(jìn)行過濾

$ tcpdump host 192.168.10.100

主程序 + 參數(shù)名+ 參數(shù)值 這樣的組合才是我們正常認(rèn)知里面命令行該有的樣子。

可 tcpdump 卻不走尋常路谷饿,我們居然還可以在 host 前再加一個(gè)限定詞抢野,來縮小過濾的范圍?

$ tcpdump src host 192.168.10.100

從字面上理解各墨,確實(shí)很容易理解,但是這不符合編寫命令行程序的正常邏輯启涯,導(dǎo)致我們會(huì)有所疑慮:

  1. 除了 src 贬堵,dst恃轩,可還有其它可以用的限定詞?

  2. src黎做,host 應(yīng)該如何理解它們叉跛,叫參數(shù)名?不合適蒸殿,因?yàn)?src 明顯不合適筷厘。

如果你在網(wǎng)上看到有關(guān) tcpdump 的博客、教程宏所,無一不是給你一個(gè)參數(shù)組合酥艳,告訴你這是實(shí)現(xiàn)了怎樣的一個(gè)過濾器?這樣的教學(xué)方式爬骤,很容易讓你依賴別人的文章來使用 tcpdump充石,而不能將 tcpdump 這樣神器消化,達(dá)到靈活應(yīng)用霞玄,靈活搭配過濾器的效果骤铃。

上面加了 src 本身就顛覆了我們的認(rèn)知,你可知道在 src 之前還可以加更多的條件坷剧,比如 tcp, udp, icmp 等詞惰爬,在你之前的基礎(chǔ)上再過濾一層。

$ tcpdump tcp src host 192.168.10.100

這種參數(shù)的不確定性惫企,讓大多數(shù)人對(duì) tcpdump 的學(xué)習(xí)始終無法得其精髓撕瞧。

因此,在學(xué)習(xí) tcpdump 之前雅任,我覺得有必要要先讓你知道:tcpdump 的參數(shù)是如何組成的风范?這非常重要。

為此沪么,我畫了一張圖硼婿,方便你直觀的理解 tcpdump 的各種參數(shù):

image
  1. option 可選參數(shù):將在后邊一一解釋,對(duì)應(yīng)本文 第四節(jié):可選參數(shù)解析

  2. proto 類過濾器:根據(jù)協(xié)議進(jìn)行過濾禽车,可識(shí)別的關(guān)鍵詞有:upd, udp, icmp, ip, ip6, arp, rarp,ether,wlan, fddi, tr, decnet

  3. type 類過濾器:可識(shí)別的關(guān)鍵詞有:host, net, port, portrange寇漫,這些詞后邊需要再接參數(shù)。

  4. direction 類過濾器:根據(jù)數(shù)據(jù)流向進(jìn)行過濾殉摔,可識(shí)別的關(guān)鍵字有:src, dst井濒,同時(shí)你可以使用邏輯運(yùn)算符進(jìn)行組合,比如 src or dst

proto豫领、type纪隙、direction 這三類過濾器的內(nèi)容比較簡(jiǎn)單,也最常用,因此我將其放在最前面瓤湘,也就是 第三節(jié):常規(guī)過濾規(guī)則一起介紹瓢颅。

而 option 可選的參數(shù)非常多,有的甚至也不經(jīng)常用到弛说,因此我將其放到后面一點(diǎn)挽懦,也就是 第四節(jié):可選參數(shù)解析

當(dāng)你看完前面六節(jié),你對(duì) tcpdump 的認(rèn)識(shí)會(huì)上了一個(gè)臺(tái)階木人,至少能夠滿足你 80% 的使用需求信柿。

你一定會(huì)問了,還有 20% 呢醒第?

其實(shí) tcpdump 還有一些過濾關(guān)鍵詞渔嚷,它不符合以上四種過濾規(guī)則,可能需要你單獨(dú)記憶淘讥。關(guān)于這部分我會(huì)在 第六節(jié):特殊過濾規(guī)則 里進(jìn)行介紹圃伶。

2. 理解 tcpdump 的輸出

2.1 輸出內(nèi)容結(jié)構(gòu)

tcpdump 輸出的內(nèi)容雖然多,卻很規(guī)律蒲列。

這里以我隨便抓取的一個(gè) tcp 包為例來看一下

21:26:49.013621 IP 172.20.20.1.15605 > 172.20.20.2.5920: Flags [P.], seq 49:97, ack 106048, win 4723, length 48

從上面的輸出來看窒朋,可以總結(jié)出:

  1. 第一列:時(shí)分秒毫秒 21:26:49.013621

  2. 第二列:網(wǎng)絡(luò)協(xié)議 IP

  3. 第三列:發(fā)送方的ip地址+端口號(hào),其中172.20.20.1是 ip蝗岖,而15605 是端口號(hào)

  4. 第四列:箭頭 >侥猩, 表示數(shù)據(jù)流向

  5. 第五列:接收方的ip地址+端口號(hào),其中 172.20.20.2 是 ip抵赢,而5920 是端口號(hào)

  6. 第六列:冒號(hào)

  7. 第七列:數(shù)據(jù)包內(nèi)容欺劳,包括Flags 標(biāo)識(shí)符,seq 號(hào)铅鲤,ack 號(hào)划提,win 窗口,數(shù)據(jù)長度 length邢享,其中 [P.] 表示 PUSH 標(biāo)志位為 1鹏往,更多標(biāo)識(shí)符見下面

2.2 Flags 標(biāo)識(shí)符

使用 tcpdump 抓包后,會(huì)遇到的 TCP 報(bào)文 Flags骇塘,有以下幾種:

  • [S] : SYN(開始連接)

  • [P] : PSH(推送數(shù)據(jù))

  • [F] : FIN (結(jié)束連接)

  • [R] : RST(重置連接)

  • [.] : 沒有 Flag伊履,由于除了 SYN 包外所有的數(shù)據(jù)包都有ACK,所以一般這個(gè)標(biāo)志也可表示 ACK

3. 常規(guī)過濾規(guī)則

3.1 基于IP地址過濾:host

使用 host 就可以指定 host ip 進(jìn)行過濾

$ tcpdump host 192.168.10.100

數(shù)據(jù)包的 ip 可以再細(xì)分為源ip和目標(biāo)ip兩種

# 根據(jù)源ip進(jìn)行過濾
$ tcpdump -i eth2 src 192.168.10.100

# 根據(jù)目標(biāo)ip進(jìn)行過濾
$ tcpdump -i eth2 dst 192.168.10.200

3.2 基于網(wǎng)段進(jìn)行過濾:net

若你的ip范圍是一個(gè)網(wǎng)段款违,可以直接這樣指定

$ tcpdump net 192.168.10.0/24

網(wǎng)段同樣可以再細(xì)分為源網(wǎng)段和目標(biāo)網(wǎng)段

# 根據(jù)源網(wǎng)段進(jìn)行過濾
$ tcpdump src net 192.168

# 根據(jù)目標(biāo)網(wǎng)段進(jìn)行過濾
$ tcpdump dst net 192.168

3.3 基于端口進(jìn)行過濾:port

使用 port 就可以指定特定端口進(jìn)行過濾

$ tcpdump port 8088

端口同樣可以再細(xì)分為源端口唐瀑,目標(biāo)端口

# 根據(jù)源端口進(jìn)行過濾
$ tcpdump src port 8088

# 根據(jù)目標(biāo)端口進(jìn)行過濾
$ tcpdump dst port 8088

如果你想要同時(shí)指定兩個(gè)端口你可以這樣寫

$ tcpdump port 80 or port 8088

但也可以簡(jiǎn)寫成這樣

$ tcpdump port 80 or 8088

如果你的想抓取的不再是一兩個(gè)端口,而是一個(gè)范圍插爹,一個(gè)一個(gè)指定就非常麻煩了哄辣,此時(shí)你可以這樣指定一個(gè)端口段。

$ tcpdump portrange 8000-8080
$ tcpdump src portrange 8000-8080
$ tcpdump dst portrange 8000-8080

對(duì)于一些常見協(xié)議的默認(rèn)端口,我們還可以直接使用協(xié)議名柔滔,而不用具體的端口號(hào)

比如 http == 80溢陪,https == 443 等

$ tcpdump tcp port http

3.4 基于協(xié)議進(jìn)行過濾:proto

常見的網(wǎng)絡(luò)協(xié)議有:tcp, udp, icmp, http, ip,ipv6 等

若你只想查看 icmp 的包,可以直接這樣寫

$ tcpdump icmp

protocol 可選值:ip, ip6, arp, rarp, atalk, aarp, decnet, sca, lat, mopdl, moprc, iso, stp, ipx, or netbeui

3.5 基本IP協(xié)議的版本進(jìn)行過濾

當(dāng)你想查看 tcp 的包睛廊,你也許會(huì)這樣子寫

$ tcpdump tcp

這樣子寫也沒問題,就是不夠精準(zhǔn)杉编,為什么這么說呢超全?

ip 根據(jù)版本的不同,可以再細(xì)分為 IPv4 和 IPv6 兩種邓馒,如果你只指定了 tcp嘶朱,這兩種其實(shí)都會(huì)包含在內(nèi)。

那有什么辦法光酣,能夠?qū)?IPv4 和 IPv6 區(qū)分開來呢疏遏?

很簡(jiǎn)單,如果是 IPv4 的 tcp 包 救军,就這樣寫(友情提示:數(shù)字 6 表示的是 tcp 在ip報(bào)文中的編號(hào)财异。)

$ tcpdump 'ip proto tcp'

# or

$ tcpdump ip proto 6

# or

$ tcpdump 'ip protochain tcp'

# or 
$ tcpdump ip protochain 6

而如果是 IPv6 的 tcp 包 ,就這樣寫

$ tcpdump 'ip6 proto tcp'

# or

$ tcpdump ip6 proto 6

# or

$ tcpdump 'ip6 protochain tcp'

# or 
$ tcpdump ip6 protochain 6

關(guān)于上面這幾個(gè)命令示例唱遭,有兩點(diǎn)需要注意:

  1. 跟在 proto 和 protochain 后面的如果是 tcp, udp, icmp 戳寸,那么過濾器需要用引號(hào)包含,這是因?yàn)?tcp,udp, icmp 是 tcpdump 的關(guān)鍵字拷泽。

  2. 跟在ip 和 ip6 關(guān)鍵字后面的 proto 和 protochain 是兩個(gè)新面孔疫鹊,看起來用法類似,它們是否等價(jià)司致,又有什么區(qū)別呢拆吆?

關(guān)于第二點(diǎn),網(wǎng)絡(luò)上沒有找到很具體的答案脂矫,我只能通過 man tcpdump 的提示枣耀, 給出自己的個(gè)人猜測(cè),但不保證正確羹唠。

proto 后面跟的 <protocol> 的關(guān)鍵詞是固定的奕枢,只能是 ip, ip6, arp, rarp, atalk, aarp, decnet, sca, lat, mopdl, moprc, iso, stp, ipx, or netbeui 這里面的其中一個(gè)。

而 protochain 后面跟的 protocol 要求就沒有那么嚴(yán)格佩微,它可以是任意詞缝彬,只要 tcpdump 的 IP 報(bào)文頭部里的 protocol 字段為 <protocol> 就能匹配上。

理論上來講哺眯,下面兩種寫法效果是一樣的

$ tcpdump 'ip && tcp'
$ tcpdump 'ip proto tcp'

同樣的谷浅,這兩種寫法也是一樣的

$ tcpdump 'ip6 && tcp'
$ tcpdump 'ip6 proto tcp'

4. 可選參數(shù)解析

4.1 設(shè)置不解析域名提升速度

  • -n:不把ip轉(zhuǎn)化成域名,直接顯示 ip,避免執(zhí)行 DNS lookups 的過程一疯,速度會(huì)快很多

  • -nn:不把協(xié)議和端口號(hào)轉(zhuǎn)化成名字撼玄,速度也會(huì)快很多。

  • -N:不打印出host 的域名部分.墩邀。比如,掌猛,如果設(shè)置了此選現(xiàn),tcpdump 將會(huì)打印'nic' 而不是 'nic.ddn.mil'.

4.2 過濾結(jié)果輸出到文件

使用 tcpdump 工具抓到包后眉睹,往往需要再借助其他的工具進(jìn)行分析荔茬,比如常見的 wireshark 。

而要使用wireshark 竹海,我們得將 tcpdump 抓到的包數(shù)據(jù)生成到文件中慕蔚,最后再使用 wireshark 打開它即可。

使用 -w 參數(shù)后接一個(gè)以 .pcap 后綴命令的文件名斋配,就可以將 tcpdump 抓到的數(shù)據(jù)保存到文件中孔飒。

$ tcpdump icmp -w icmp.pcap

4.3 從文件中讀取包數(shù)據(jù)

使用 -w 是寫入數(shù)據(jù)到文件,而使用 -r 是從文件中讀取數(shù)據(jù)艰争。

讀取后坏瞄,我們照樣可以使用上述的過濾器語法進(jìn)行過濾分析。

$ tcpdump icmp -r all.pcap

4.4 控制詳細(xì)內(nèi)容的輸出

  • -v:產(chǎn)生詳細(xì)的輸出. 比如包的TTL园细,id標(biāo)識(shí)惦积,數(shù)據(jù)包長度,以及IP包的一些選項(xiàng)猛频。同時(shí)它還會(huì)打開一些附加的包完整性檢測(cè)狮崩,比如對(duì)IP或ICMP包頭部的校驗(yàn)和。

  • -vv:產(chǎn)生比-v更詳細(xì)的輸出. 比如NFS回應(yīng)包中的附加域?qū)?huì)被打印, SMB數(shù)據(jù)包也會(huì)被完全解碼鹿寻。(摘自網(wǎng)絡(luò)睦柴,目前我還未使用過)

  • -vvv:產(chǎn)生比-vv更詳細(xì)的輸出。比如 telent 時(shí)所使用的SB, SE 選項(xiàng)將會(huì)被打印, 如果telnet同時(shí)使用的是圖形界面毡熏,其相應(yīng)的圖形選項(xiàng)將會(huì)以16進(jìn)制的方式打印出來(摘自網(wǎng)絡(luò)坦敌,目前我還未使用過)

4.5 控制時(shí)間的顯示

  • -t:在每行的輸出中不輸出時(shí)間

  • -tt:在每行的輸出中會(huì)輸出時(shí)間戳

  • -ttt:輸出每兩行打印的時(shí)間間隔(以毫秒為單位)

  • -tttt:在每行打印的時(shí)間戳之前添加日期的打印(此種選項(xiàng)痢法,輸出的時(shí)間最直觀)

4.6 顯示數(shù)據(jù)包的頭部

  • -x:以16進(jìn)制的形式打印每個(gè)包的頭部數(shù)據(jù)(但不包括數(shù)據(jù)鏈路層的頭部)

  • -xx:以16進(jìn)制的形式打印每個(gè)包的頭部數(shù)據(jù)(包括數(shù)據(jù)鏈路層的頭部)

  • -X:以16進(jìn)制和 ASCII碼形式打印出每個(gè)包的數(shù)據(jù)(但不包括連接層的頭部)狱窘,這在分析一些新協(xié)議的數(shù)據(jù)包很方便。

  • -XX:以16進(jìn)制和 ASCII碼形式打印出每個(gè)包的數(shù)據(jù)(包括連接層的頭部)财搁,這在分析一些新協(xié)議的數(shù)據(jù)包很方便蘸炸。

4.7 過濾指定網(wǎng)卡的數(shù)據(jù)包

  • -i:指定要過濾的網(wǎng)卡接口,如果要查看所有網(wǎng)卡尖奔,可以 -i any

4.8 過濾特定流向的數(shù)據(jù)包

  • -Q:選擇是入方向還是出方向的數(shù)據(jù)包搭儒,可選項(xiàng)有:in, out, inout穷当,也可以使用 --direction=[direction] 這種寫法

4.9 其他常用的一些參數(shù)

  • -A:以ASCII碼方式顯示每一個(gè)數(shù)據(jù)包(不顯示鏈路層頭部信息). 在抓取包含網(wǎng)頁數(shù)據(jù)的數(shù)據(jù)包時(shí), 可方便查看數(shù)據(jù)

  • -l : 基于行的輸出,便于你保存查看淹禾,或者交給其它工具分析

  • -q : 簡(jiǎn)潔地打印輸出馁菜。即打印很少的協(xié)議相關(guān)信息, 從而輸出行都比較簡(jiǎn)短.

  • -c : 捕獲 count 個(gè)包 tcpdump 就退出

  • -s : tcpdump 默認(rèn)只會(huì)截取前 96 字節(jié)的內(nèi)容,要想截取所有的報(bào)文內(nèi)容铃岔,可以使用 -s number汪疮, number 就是你要截取的報(bào)文字節(jié)數(shù),如果是 0 的話德撬,表示截取報(bào)文全部內(nèi)容铲咨。

  • -S : 使用絕對(duì)序列號(hào),而不是相對(duì)序列號(hào)

  • -C:file-size蜓洪,tcpdump 在把原始數(shù)據(jù)包直接保存到文件中之前, 檢查此文件大小是否超過file-size. 如果超過了, 將關(guān)閉此文件,另創(chuàng)一個(gè)文件繼續(xù)用于原始數(shù)據(jù)包的記錄. 新創(chuàng)建的文件名與-w 選項(xiàng)指定的文件名一致, 但文件名后多了一個(gè)數(shù)字.該數(shù)字會(huì)從1開始隨著新創(chuàng)建文件的增多而增加. file-size的單位是百萬字節(jié)(nt: 這里指1,000,000個(gè)字節(jié),并非1,048,576個(gè)字節(jié), 后者是以1024字節(jié)為1k, 1024k字節(jié)為1M計(jì)算所得, 即1M=1024 * 1024 = 1,048,576)

  • -F:使用file 文件作為過濾條件表達(dá)式的輸入, 此時(shí)命令行上的輸入將被忽略.

4.10 對(duì)輸出內(nèi)容進(jìn)行控制的參數(shù)

  • -D : 顯示所有可用網(wǎng)絡(luò)接口的列表

  • -e : 每行的打印輸出中將包括數(shù)據(jù)包的數(shù)據(jù)鏈路層頭部信息

  • -E : 揭秘IPSEC數(shù)據(jù)

  • -L :列出指定網(wǎng)絡(luò)接口所支持的數(shù)據(jù)鏈路層的類型后退出

  • -Z:后接用戶名,在抓包時(shí)會(huì)受到權(quán)限的限制坯苹。如果以root用戶啟動(dòng)tcpdump隆檀,tcpdump將會(huì)有超級(jí)用戶權(quán)限。

  • -d:打印出易讀的包匹配碼

  • -dd:以C語言的形式打印出包匹配碼.

  • -ddd:以十進(jìn)制數(shù)的形式打印出包匹配碼

5. 過濾規(guī)則組合

有編程基礎(chǔ)的同學(xué)粹湃,對(duì)于下面三個(gè)邏輯運(yùn)算符應(yīng)該不陌生了吧

  • and:所有的條件都需要滿足恐仑,也可以表示為 &&

  • or:只要有一個(gè)條件滿足就可以,也可以表示為 ||

  • not:取反为鳄,也可以使用 !

舉個(gè)例子裳仆,我想需要抓一個(gè)來自10.5.2.3,發(fā)往任意主機(jī)的3389端口的包

$ tcpdump src 10.5.2.3 and dst port 3389

當(dāng)你在使用多個(gè)過濾器進(jìn)行組合時(shí)孤钦,有可能需要用到括號(hào)歧斟,而括號(hào)在 shell 中是特殊符號(hào),因?yàn)槟阈枰褂靡?hào)將其包含偏形。例子如下:

$ tcpdump 'src 10.0.2.4 and (dst port 3389 or 22)'

而在單個(gè)過濾器里静袖,常常會(huì)判斷一條件是否成立,這時(shí)候俊扭,就要使用下面兩個(gè)符號(hào)

  • =:判斷二者相等

  • ==:判斷二者相等

  • !=:判斷二者不相等

當(dāng)你使用這兩個(gè)符號(hào)時(shí)队橙,tcpdump 還提供了一些關(guān)鍵字的接口來方便我們進(jìn)行判斷,比如

  • if:表示網(wǎng)卡接口名萨惑、

  • proc:表示進(jìn)程名

  • pid:表示進(jìn)程 id

  • svc:表示 service class

  • dir:表示方向捐康,in 和 out

  • eproc:表示 effective process name

  • epid:表示 effective process ID

比如我現(xiàn)在要過濾來自進(jìn)程名為 nc 發(fā)出的流經(jīng) en0 網(wǎng)卡的數(shù)據(jù)包,或者不流經(jīng) en0 的入方向數(shù)據(jù)包庸蔼,可以這樣子寫

$ tcpdump "( if=en0 and proc =nc ) || (if != en0 and dir=in)"

6. 特殊過濾規(guī)則

5.1 根據(jù) tcpflags 進(jìn)行過濾

通過上一篇文章解总,我們知道了 tcp 的首部有一個(gè)標(biāo)志位。

image

tcpdump 支持我們根據(jù)數(shù)據(jù)包的標(biāo)志位進(jìn)行過濾

proto [ expr:size ]
  • proto:可以是熟知的協(xié)議之一(如ip朱嘴,arp倾鲫,tcp粗合,udp,icmp乌昔,ipv6)

  • expr:可以是數(shù)值隙疚,也可以是一個(gè)表達(dá)式,表示與指定的協(xié)議頭開始處的字節(jié)偏移量磕道。

  • size:是可選的供屉,表示從字節(jié)偏移量開始取的字節(jié)數(shù)量。

接下來溺蕉,我將舉幾個(gè)例子伶丐,讓人明白它的寫法,不過在那之前疯特,有幾個(gè)點(diǎn)需要你明白哗魂,這在后面的例子中會(huì)用到:

1、tcpflags 可以理解為是一個(gè)別名常量漓雅,相當(dāng)于 13录别,它代表著與指定的協(xié)議頭開頭相關(guān)的字節(jié)偏移量,也就是標(biāo)志位邻吞,所以 tcp[tcpflags] 等價(jià)于 tcp[13] 组题,對(duì)應(yīng)下圖中的報(bào)文位置。

image

2抱冷、tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg 這些同樣可以理解為別名常量崔列,分別代表 1,2旺遮,4赵讯,8,16趣效,32瘦癌,64。這些數(shù)字是如何計(jì)算出來的呢跷敬?

以 tcp-syn 為例讯私,你可以參照下面這張圖,計(jì)算出來的值 是就是 2

image

由于數(shù)字不好記憶西傀,所以一般使用這樣的“別名常量”表示斤寇。

因此當(dāng)下面這個(gè)表達(dá)式成立時(shí),就代表這個(gè)包是一個(gè) syn 包拥褂。

tcp[tcpflags] == tcp-syn

要抓取特定數(shù)據(jù)包娘锁,方法有很多種。

下面以最常見的 syn包為例饺鹃,演示一下如何用 tcpdump 抓取到 syn 包莫秆,而其他的類型的包也是同樣的道理间雀。

據(jù)我總結(jié),主要有三種寫法:

1镊屎、第一種寫法:使用數(shù)字表示偏移量

$ tcpdump -i eth0 "tcp[13] & 2 != 0" 

2惹挟、第二種寫法:使用別名常量表示偏移量

$ tcpdump -i eth0 "tcp[tcpflags] & tcp-syn != 0" 

3、第三種寫法:使用混合寫法

$ tcpdump -i eth0 "tcp[tcpflags] & 2 != 0" 

# or

$ tcpdump -i eth0 "tcp[13] & tcp-syn != 0" 

如果我想同時(shí)捕獲多種類型的包呢缝驳,比如 syn + ack 包

1连锯、第一種寫法

$ tcpdump -i eth0 'tcp[13] == 2 or tcp[13] == 16'

2、第二種寫法

$ tcpdump -i eth0 'tcp[tcpflags] == tcp-syn or tcp[tcpflags] == tcp-ack'

3用狱、第三種寫法

$ tcpdump -i eth0 "tcp[tcpflags] & (tcp-syn|tcp-ack) != 0" 

4运怖、第四種寫法:注意這里是 單個(gè)等號(hào),而不是像上面一樣兩個(gè)等號(hào)夏伊,18(syn+ack) = 2(syn) + 16(ack)

$ tcpdump -i eth0 'tcp[13] = 18'

# or

$ tcpdump -i eth0 'tcp[tcpflags] = 18'

tcp 中有 類似 tcp-syn 的別名常量摇展,其他協(xié)議也是有的,比如 icmp 協(xié)議溺忧,可以使用的別名常量有

icmp-echoreply, icmp-unreach, icmp-sourcequench, 
icmp-redirect, icmp-echo, icmp-routeradvert,
icmp-routersolicit, icmp-timx-ceed, icmp-paramprob, 
icmp-tstamp, icmp-tstampreply,icmp-ireq, 
icmp-ireqreply, icmp-maskreq, icmp-maskreply

5.2 基于包大小進(jìn)行過濾

若你想查看指定大小的數(shù)據(jù)包吗购,也是可以的

$ tcpdump less 32 
$ tcpdump greater 64 
$ tcpdump <= 128

5.3 根據(jù) mac 地址進(jìn)行過濾

例子如下,其中 ehost 是記錄在 /etc/ethers 里的 name

$ tcpdump ether host [ehost]
$ tcpdump ether dst    [ehost]
$ tcpdump ether src    [ehost]

5.4 過濾通過指定網(wǎng)關(guān)的數(shù)據(jù)包

$ tcpdump gateway [host]

5.5 過濾廣播/多播數(shù)據(jù)包

$ tcpdump ether broadcast
$ tcpdump ether multicast

$ tcpdump ip broadcast
$ tcpdump ip multicast

$ tcpdump ip6 multicast

7. 如何抓取到更精準(zhǔn)的包砸狞?

先給你拋出一個(gè)問題:如果我只想抓取 HTTP 的 POST 請(qǐng)求該如何寫呢?

如果只學(xué)習(xí)了上面的內(nèi)容镀梭,恐怕你還是無法寫法滿足這個(gè)抓取需求的過濾器刀森。

在學(xué)習(xí)之前,我先給出答案报账,然后再剖析一下研底,這個(gè)過濾器是如何生效的,居然能讓我們對(duì)包內(nèi)的內(nèi)容進(jìn)行判斷透罢。

$ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4]'

命令里的可選參數(shù)榜晦,在前面的內(nèi)容里已經(jīng)詳細(xì)講過了。這里不再細(xì)講羽圃。

本節(jié)的重點(diǎn)是引號(hào)里的內(nèi)容乾胶,看起來很復(fù)雜的樣子。

將它逐一分解朽寞,我們只要先理解了下面幾種用法识窿,就能明白

  • tcp[n]:表示 tcp 報(bào)文里 第 n 個(gè)字節(jié)

  • tcp[n:c]:表示 tcp 報(bào)文里從第n個(gè)字節(jié)開始取 c 個(gè)字節(jié),tcp[12:1] 表示從報(bào)文的第12個(gè)字節(jié)(因?yàn)橛械?個(gè)字節(jié)脑融,所以這里的12其實(shí)表示的是13)開始算起取一個(gè)字節(jié)喻频,也就是 8 個(gè)bit。查看 tcp 的報(bào)文首部結(jié)構(gòu)肘迎,可以得知這 8 個(gè)bit 其實(shí)就是下圖中的紅框圈起來的位置甥温,而在這里我們只要前面 4個(gè)bit锻煌,也就是實(shí)際數(shù)據(jù)在整個(gè)報(bào)文首部中的偏移量。

    image
  • &:是位運(yùn)算里的 and 操作符姻蚓,比如 0011 & 0010 = 0010

  • >>:是位運(yùn)算里的右移操作宋梧,比如 0111 >> 2 = 0011

  • 0xf0:是 10 進(jìn)制的 240 的 16 進(jìn)制表示,但對(duì)于位操作來說史简,10進(jìn)制和16進(jìn)制都將毫無意義乃秀,我們需要的是二進(jìn)制,將其轉(zhuǎn)換成二進(jìn)制后是:11110000圆兵,這個(gè)數(shù)有什么特點(diǎn)呢跺讯?前面?zhèn)€ 4bit 全部是 1,后面4個(gè)bit全部是0殉农,往后看你就知道這個(gè)特點(diǎn)有什么用了刀脏。

分解完后,再慢慢合并起來看

1超凳、tcp[12:1] & 0xf0 其實(shí)并不直觀愈污,但是我們將它換一種寫法,就好看多了轮傍,假設(shè) tcp 報(bào)文中的 第12 個(gè)字節(jié)是這樣組成的 10110000暂雹,那么這個(gè)表達(dá)式就可以變成 10110110 && 11110000 = 10110000,得到了 10110000 后创夜,再進(jìn)入下一步杭跪。

2、tcp[12:1] & 0xf0) >> 2 :如果你不理解 tcp 報(bào)文首部里的數(shù)據(jù)偏移驰吓,請(qǐng)先點(diǎn)擊這個(gè)前往我的上一篇文章涧尿,搞懂?dāng)?shù)據(jù)偏移的意義,否則我保證你這里會(huì)絕對(duì)會(huì)聽懵了檬贰。

tcp[12:1] & 0xf0) >> 2 這個(gè)表達(dá)式實(shí)際是 (tcp[12:1] & 0xf0) >> 4 ) << 2 的簡(jiǎn)寫形式姑廉。所以要搞懂 tcp[12:1] & 0xf0) >> 2 只要理解了(tcp[12:1] & 0xf0) >> 4 ) << 2 就行了 。

從上一步我們算出了 tcp[12:1] & 0xf0 的值其實(shí)是一個(gè)字節(jié)翁涤,也就是 8 個(gè)bit桥言,但是你再回去看下上面的 tcp 報(bào)文首部結(jié)構(gòu)圖,表示數(shù)據(jù)偏移量的只有 4個(gè)bit迷雪,也就是說 上面得到的值 10110000限书,前面 4 位(1011)才是正確的偏移量,那么為了得到 1011章咧,只需要將 10110000 右移4位即可倦西,也就是 tcp[12:1] & 0xf0) >> 4,至此我們是不是已經(jīng)得出了實(shí)際數(shù)據(jù)的正確位置呢赁严,很遺憾還沒有扰柠,前一篇文章里我們講到 Data Offset 的單位是 4個(gè)字節(jié)粉铐,因?yàn)橐獙?1011 乘以 4才可以,除以4在位運(yùn)算中相當(dāng)于左移2位卤档,也就是 <<2蝙泼,與前面的 >>4 結(jié)合起來一起算的話,最終的運(yùn)算可以簡(jiǎn)化為 >>2

至此劝枣,我們終于得出了實(shí)際數(shù)據(jù)開始的位置是 tcp[12:1] & 0xf0) >> 2 (單位是字節(jié))汤踏。

找到了數(shù)據(jù)的起點(diǎn)后,可別忘了我們的目的是從數(shù)據(jù)中打到 HTTP 請(qǐng)求的方法舔腾,是 GET 呢 還是 POST 溪胶,或者是其他的?

有了上面的經(jīng)驗(yàn)稳诚,我們自然懂得使用 tcp[((tcp[12:1] & 0xf0) >> 2):4] 從數(shù)據(jù)開始的位置再取出四個(gè)字節(jié)哗脖,然后將結(jié)果與 GET (注意 GET最后還有個(gè)空格)的 16進(jìn)制寫法(也就是 0x47455420)進(jìn)行比對(duì)。

0x47   -->   71    -->  G
0x45   -->   69    -->  E
0x54   -->   84    -->  T
0x20   -->   32    -->  空格
image

如果相等扳还,則該表達(dá)式為True才避,tcpdump 認(rèn)為這就是我們所需要抓的數(shù)據(jù)包,將其輸出到我們的終端屏幕上氨距。

8. 抓包實(shí)戰(zhàn)應(yīng)用例子

以下例子摘自:https://fuckcloudnative.io/posts/tcpdump-examples/

8.1 提取 HTTP 的 User-Agent

從 HTTP 請(qǐng)求頭中提取 HTTP 用戶代理:

$ tcpdump -nn -A -s1500 -l | grep "User-Agent:"

通過 egrep 可以同時(shí)提取用戶代理和主機(jī)名(或其他頭文件):

$ tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host:'

8.2 抓取 HTTP GET 和 POST 請(qǐng)求

抓取 HTTP GET 請(qǐng)求包:

$ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'

# or

$ tcpdump -vvAls0 | grep 'GET'

可以抓取 HTTP POST 請(qǐng)求包:

$ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'

# or 

$ tcpdump -vvAls0 | grep 'POST'

注意:該方法不能保證抓取到 HTTP POST 有效數(shù)據(jù)流量桑逝,因?yàn)橐粋€(gè) POST 請(qǐng)求會(huì)被分割為多個(gè) TCP 數(shù)據(jù)包。

8.3 找出發(fā)包數(shù)最多的 IP

找出一段時(shí)間內(nèi)發(fā)包最多的 IP俏让,或者從一堆報(bào)文中找出發(fā)包最多的 IP肢娘,可以使用下面的命令:

$ tcpdump -nnn -t -c 200 | cut -f 1,2,3,4 -d '.' | sort | uniq -c | sort -nr | head -n 20
  • cut -f 1,2,3,4 -d '.' : 以 . 為分隔符,打印出每行的前四列舆驶。即 IP 地址。

  • sort | uniq -c : 排序并計(jì)數(shù)

  • sort -nr : 按照數(shù)值大小逆向排序

8.4 抓取 DNS 請(qǐng)求和響應(yīng)

DNS 的默認(rèn)端口是 53而钞,因此可以通過端口進(jìn)行過濾

$ tcpdump -i any -s0 port 53

8.5 切割 pcap 文件

當(dāng)抓取大量數(shù)據(jù)并寫入文件時(shí)沙廉,可以自動(dòng)切割為多個(gè)大小相同的文件。例如臼节,下面的命令表示每 3600 秒創(chuàng)建一個(gè)新文件 capture-(hour).pcap撬陵,每個(gè)文件大小不超過 200*1000000 字節(jié):

$ tcpdump  -w /tmp/capture-%H.pcap -G 3600 -C 200

這些文件的命名為 capture-{1-24}.pcap,24 小時(shí)之后网缝,之前的文件就會(huì)被覆蓋巨税。

8.6 提取 HTTP POST 請(qǐng)求中的密碼

從 HTTP POST 請(qǐng)求中提取密碼和主機(jī)名:

$ tcpdump -s 0 -A -n -l | egrep -i "POST /|pwd=|passwd=|password=|Host:"

8.7 提取 HTTP 請(qǐng)求的 URL

提取 HTTP 請(qǐng)求的主機(jī)名和路徑:

$ tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:"

8.8 抓取 HTTP 有效數(shù)據(jù)包

抓取 80 端口的 HTTP 有效數(shù)據(jù)包,排除 TCP 連接建立過程的數(shù)據(jù)包(SYN / FIN / ACK):

$ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

8.9 結(jié)合 Wireshark 進(jìn)行分析

通常 Wireshark(或 tshark)比 tcpdump 更容易分析應(yīng)用層協(xié)議粉臊。一般的做法是在遠(yuǎn)程服務(wù)器上先使用 tcpdump 抓取數(shù)據(jù)并寫入文件草添,然后再將文件拷貝到本地工作站上用 Wireshark 分析。

還有一種更高效的方法扼仲,可以通過 ssh 連接將抓取到的數(shù)據(jù)實(shí)時(shí)發(fā)送給 Wireshark 進(jìn)行分析远寸。以 MacOS 系統(tǒng)為例抄淑,可以通過 brew cask install wireshark 來安裝,然后通過下面的命令來分析:

$ ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - not port 22' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -

例如驰后,如果想分析 DNS 協(xié)議肆资,可以使用下面的命令:

$ ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - port 53' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -

抓取到的數(shù)據(jù):

image

-c 選項(xiàng)用來限制抓取數(shù)據(jù)的大小。如果不限制大小灶芝,就只能通過 ctrl-c 來停止抓取郑原,這樣一來不僅關(guān)閉了 tcpdump,也關(guān)閉了 wireshark夜涕。

到這里犯犁,我已經(jīng)將我所知道的 tcpdump 的用法全部說了一遍,如果你有認(rèn)真地看完本文钠乏,相信會(huì)有不小的收獲栖秕,掌握一個(gè)上手的抓包工具,對(duì)于以后我們學(xué)習(xí)網(wǎng)絡(luò)晓避、分析網(wǎng)絡(luò)協(xié)議簇捍、以及定位網(wǎng)絡(luò)問題,會(huì)很有幫助俏拱,而 tcpdump 是我推薦的一個(gè)抓包工具暑塑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锅必,隨后出現(xiàn)的幾起案子事格,更是在濱河造成了極大的恐慌,老刑警劉巖搞隐,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驹愚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡劣纲,警方通過查閱死者的電腦和手機(jī)逢捺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來癞季,“玉大人劫瞳,你說我怎么就攤上這事”疗猓” “怎么了志于?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長废睦。 經(jīng)常有香客問我伺绽,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任憔恳,我火速辦了婚禮瓤荔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钥组。我一直安慰自己输硝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布程梦。 她就那樣靜靜地躺著点把,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屿附。 梳的紋絲不亂的頭發(fā)上郎逃,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音挺份,去河邊找鬼褒翰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛匀泊,可吹牛的內(nèi)容都是我干的优训。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼各聘,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼揣非!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起躲因,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤早敬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后大脉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搞监,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年镰矿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腺逛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衡怀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出安疗,到底是詐尸還是另有隱情抛杨,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布荐类,位于F島的核電站怖现,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屈嗤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一潘拨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饶号,春花似錦铁追、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至算谈,卻和暖如春涩禀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背然眼。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工艾船, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人高每。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓屿岂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親觉义。 傳聞我的和親對(duì)象是個(gè)殘疾皇子雁社,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348