日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tcpdump详解

發(fā)布時間:2023/12/31 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tcpdump详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址:全網(wǎng)最詳細的 tcpdump 使用指南 - 王一白 - 博客園

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

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

可以用wireshark 讀取tcpdump 生成的pcap文件,用wireshark的圖形化界面分析tcpdump 結(jié)果數(shù)據(jù)。

在講解之前,有兩點需要聲明:

  • 第三節(jié)到第六節(jié)里的 tcpdump 命令示例,只為了說明參數(shù)的使用,并不一定就能抓到包,如果要精準(zhǔn)抓到你所需要的包,需要配合第五節(jié)的邏輯邏輯運算符進行組合搭配。
  • 不同 Linux 發(fā)行版下、不同版本的 tcpdump 可能有小許差異, 本文是基于 CentOS 7.2 的 4.5.1 版本的tcpdump 進行學(xué)習(xí)的,若在你的環(huán)境中無法使用,請參考?man tcpdump?進行針對性學(xué)習(xí)。
  • 1. tcpdump 核心參數(shù)圖解

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

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

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

    tcpdump 的參數(shù)非常的多,初學(xué)者在沒有掌握 tcpdump 時,會對這個命令的眾多參數(shù)產(chǎn)生很多的疑惑。

    就比如下面這個命令,我們要通過?host?參數(shù)指定 host ip 進行過濾

    $ tcpdump host 192.168.10.100

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

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

    $ tcpdump src host 192.168.10.100

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

  • 除了 src ,dst,可還有其它可以用的限定詞?

  • src,host 應(yīng)該如何理解它們,叫參數(shù)名?不合適,因為 src 明顯不合適。

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

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

    $ tcpdump tcp src host 192.168.10.100

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

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

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

  • option 可選參數(shù):將在后邊一一解釋。
  • proto 類過濾器:根據(jù)協(xié)議進行過濾,可識別的關(guān)鍵詞有: tcp, udp, icmp, ip, ip6, arp, rarp,ether,wlan, fddi, tr, decnet
  • type 類過濾器:可識別的關(guān)鍵詞有:host, net, port, portrange,這些詞后邊需要再接參數(shù)。
  • direction 類過濾器:根據(jù)數(shù)據(jù)流向進行過濾,可識別的關(guān)鍵字有:src, dst,同時你可以使用邏輯運算符進行組合,比如 src or dst
  • proto、type、direction 這三類過濾器的內(nèi)容比較簡單,也最常用,因此我將其放在最前面,也就是?第三節(jié):常規(guī)過濾規(guī)則一起介紹。

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

    當(dāng)你看完前面六節(jié),你對 tcpdump 的認識會上了一個臺階,至少能夠滿足你 80% 的使用需求。

    你一定會問了,還有 20% 呢?

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

    2. 理解 tcpdump 的輸出

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

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

    這里以我隨便抓取的一個 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é)出:

  • 第一列:時分秒毫秒 21:26:49.013621
  • 第二列:網(wǎng)絡(luò)協(xié)議 IP
  • 第三列:發(fā)送方的ip地址+端口號,其中172.20.20.1是 ip,而15605 是端口號
  • 第四列:箭頭 >, 表示數(shù)據(jù)流向
  • 第五列:接收方的ip地址+端口號,其中 172.20.20.2 是 ip,而5920 是端口號
  • 第六列:冒號
  • 第七列:數(shù)據(jù)包內(nèi)容,包括Flags 標(biāo)識符,seq 號,ack 號,win 窗口,數(shù)據(jù)長度 length,其中 [P.] 表示 PUSH 標(biāo)志位為 1,更多標(biāo)識符見下面
  • 2.2 Flags 標(biāo)識符

    使用 tcpdump 抓包后,會遇到的 TCP 報文 Flags,有以下幾種:

    • [S]?: SYN(開始連接)
    • [P]?: PSH(推送數(shù)據(jù))
    • [F]?: FIN (結(jié)束連接)
    • [R]?: RST(重置連接)
    • [.]?: 沒有 Flag (意思是除上面四種類型外的其他情況,有可能是 ACK 也有可能是 URG)

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

    3.1 基于IP地址過濾:host

    使用?host?就可以指定 host ip 進行過濾

    $?tcpdump host 192.168.10.100

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

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

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

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

    $ tcpdump net 192.168.10.0/24

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

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

    3.3 基于端口進行過濾:port

    使用?port?就可以指定特定端口進行過濾

    $ tcpdump port 8088

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

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

    如果你想要同時指定兩個端口你可以這樣寫

    $ tcpdump port 80 or port 8088

    但也可以簡寫成這樣

    $ tcpdump port 80 or 8088

    如果你的想抓取的不再是一兩個端口,而是一個范圍,一個一個指定就非常麻煩了,此時你可以這樣指定一個端口段。

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

    對于一些常見協(xié)議的默認端口,我們還可以直接使用協(xié)議名,而不用具體的端口號

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

    $ tcpdump tcp port http

    3.4 基于協(xié)議進行過濾: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é)議的版本進行過濾

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

    $ tcpdump tcp

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

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

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

    很簡單,如果是 IPv4 的 tcp 包 ,就這樣寫(友情提示:數(shù)字 6 表示的是 tcp 在ip報文中的編號。)

    $ 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)于上面這幾個命令示例,有兩點需要注意:

  • 跟在 proto 和 protochain 后面的如果是 tcp, udp, icmp ,那么過濾器需要用引號包含,這是因為 tcp,udp, icmp 是 tcpdump 的關(guān)鍵字。
  • 跟在ip 和 ip6 關(guān)鍵字后面的 proto 和 protochain 是兩個新面孔,看起來用法類似,它們是否等價,又有什么區(qū)別呢?
  • 關(guān)于第二點,網(wǎng)絡(luò)上沒有找到很具體的答案,我只能通過?man tcpdump?的提示, 給出自己的個人猜測,但不保證正確。

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

    而 protochain 后面跟的 protocol 要求就沒有那么嚴格,它可以是任意詞,只要 tcpdump 的 IP 報文頭部里的 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 的過程,速度會快很多
      -nn:不把協(xié)議和端口號轉(zhuǎn)化成名字,速度也會快很多。
      -N:不打印出host 的域名部分.。比如,,如果設(shè)置了此選現(xiàn),tcpdump 將會打印'nic' 而不是 'nic.ddn.mil'.

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

    使用 tcpdump 工具抓到包后,往往需要再借助其他的工具進行分析,比如常見的 wireshark 。

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

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

    $?tcpdump? icmp? -w? icmp.pcap

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

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

    讀取后,我們照樣可以使用上述的過濾器語法進行過濾分析。

    $ tcpdump icmp -r all.pcap

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

    • -v:產(chǎn)生詳細的輸出. 比如包的TTL,id標(biāo)識,數(shù)據(jù)包長度,以及IP包的一些選項。同時它還會打開一些附加的包完整性檢測,比如對IP或ICMP包頭部的校驗和。
    • -vv:產(chǎn)生比-v更詳細的輸出. 比如NFS回應(yīng)包中的附加域?qū)淮蛴? SMB數(shù)據(jù)包也會被完全解碼。(摘自網(wǎng)絡(luò),目前我還未使用過)
    • -vvv:產(chǎn)生比-vv更詳細的輸出。比如 telent 時所使用的SB, SE 選項將會被打印, 如果telnet同時使用的是圖形界面,其相應(yīng)的圖形選項將會以16進制的方式打印出來(摘自網(wǎng)絡(luò),目前我還未使用過)

    4.5 控制時間的顯示

    • -t:在每行的輸出中不輸出時間
    • -tt:在每行的輸出中會輸出時間戳
    • -ttt:輸出每兩行打印的時間間隔(以毫秒為單位)
    • -tttt:在每行打印的時間戳之前添加日期的打印(此種選項,輸出的時間最直觀)

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

    • -x:以16進制的形式打印每個包的頭部數(shù)據(jù)(但不包括數(shù)據(jù)鏈路層的頭部)
    • -xx:以16進制的形式打印每個包的頭部數(shù)據(jù)(包括數(shù)據(jù)鏈路層的頭部)
    • -X:以16進制和 ASCII碼形式打印出每個包的數(shù)據(jù)(但不包括連接層的頭部),這在分析一些新協(xié)議的數(shù)據(jù)包很方便。
    • -XX:以16進制和 ASCII碼形式打印出每個包的數(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ù)包,可選項有:in, out, inout,也可以使用 --direction=[direction] 這種寫法

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

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

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

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

    • -c?: 捕獲 count 個包 tcpdump 就退出

    • -s?: tcpdump 默認只會截取前?96?字節(jié)的內(nèi)容,要想截取所有的報文內(nèi)容,可以使用?-s number,?number?就是你要截取的報文字節(jié)數(shù),如果是 0 的話,表示截取報文全部內(nèi)容。

    • -S?: 使用絕對序列號,而不是相對序列號

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

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

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

    • -D?: 顯示所有可用網(wǎng)絡(luò)接口的列表
    • -e?: 每行的打印輸出中將包括數(shù)據(jù)包的數(shù)據(jù)鏈路層頭部信息
    • -E?: 揭秘IPSEC數(shù)據(jù)
    • -L?:列出指定網(wǎng)絡(luò)接口所支持的數(shù)據(jù)鏈路層的類型后退出
    • -Z:后接用戶名,在抓包時會受到權(quán)限的限制。如果以root用戶啟動tcpdump,tcpdump將會有超級用戶權(quán)限。
    • -d:打印出易讀的包匹配碼
    • -dd:以C語言的形式打印出包匹配碼.
    • -ddd:以十進制數(shù)的形式打印出包匹配碼

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

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

    • and:所有的條件都需要滿足,也可以表示為?&&
    • or:只要有一個條件滿足就可以,也可以表示為?||
    • not:取反,也可以使用?!

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

    $ tcpdump src 10.5.2.3 and dst port 3389

    當(dāng)你在使用多個過濾器進行組合時,有可能需要用到括號,而括號在 shell 中是特殊符號,因為你需要使用引號將其包含。例子如下:

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

    而在單個過濾器里,常常會判斷一條件是否成立,這時候,就要使用下面兩個符號

    • =:判斷二者相等
    • ==:判斷二者相等
    • !=:判斷二者不相等

    當(dāng)你使用這兩個符號時,tcpdump 還提供了一些關(guān)鍵字的接口來方便我們進行判斷,比如

    • if:表示網(wǎng)卡接口名、
    • proc:表示進程名
    • pid:表示進程 id
    • svc:表示 service class
    • dir:表示方向,in 和 out
    • eproc:表示 effective process name
    • epid:表示 effective process ID

    比如我現(xià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 進行過濾

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

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

    proto [ expr:size ]
    • proto:可以是熟知的協(xié)議之一(如ip,arp,tcp,udp,icmp,ipv6)

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

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

    接下來,我將舉幾個例子,讓人明白它的寫法,不過在那之前,有幾個點需要你明白,這在后面的例子中會用到:

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

    2、tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg 這些同樣可以理解為別名常量,分別代表 1,2,4,8,16,32,64。這些數(shù)字是如何計算出來的呢?

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

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

    因此當(dāng)下面這個表達式成立時,就代表這個包是一個 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"

    如果我想同時捕獲多種類型的包呢,比如 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、第四種寫法:注意這里是 單個等號,而不是像上面一樣兩個等號,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 基于包大小進行過濾

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

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

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

    例子如下,其中 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)的包?

    先給你拋出一個問題:如果我只想抓取 HTTP 的 POST 請求該如何寫呢?

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

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

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

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

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

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

    • tcp[n]:表示 tcp 報文里 第 n 個字節(jié)

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

    • &:是位運算里的 and 操作符,比如?0011 & 0010 = 0010

    • >>:是位運算里的右移操作,比如?0111 >> 2 = 0001

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

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

    1、tcp[12:1] & 0xf0?其實并不直觀,但是我們將它換一種寫法,就好看多了,假設(shè) tcp 報文中的 第12 個字節(jié)是這樣組成的?10110000,那么這個表達式就可以變成 10110110 && 11110000 = 10110000,得到了 10110000 后,再進入下一步。

    2、tcp[12:1] & 0xf0) >> 2?:如果你不理解 tcp 報文首部里的數(shù)據(jù)偏移,請先點擊這個前往我的上一篇文章,搞懂?dāng)?shù)據(jù)偏移的意義,否則我保證你這里會絕對會聽懵了。

    tcp[12:1] & 0xf0) >> 2?這個表達式實際是?(tcp[12:1] & 0xf0) >> 4 ) << 2?的簡寫形式。所以要搞懂?tcp[12:1] & 0xf0) >> 2?只要理解了(tcp[12:1] & 0xf0) >> 4 ) << 2?就行了 。

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

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

    找到了數(shù)據(jù)的起點后,可別忘了我們的目的是從數(shù)據(jù)中打到 HTTP 請求的方法,是 GET 呢 還是 POST ,或者是其他的?

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

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

    如果相等,則該表達式為True,tcpdump 認為這就是我們所需要抓的數(shù)據(jù)包,將其輸出到我們的終端屏幕上。

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

    8.1 提取 HTTP 的 User-Agent

    從 HTTP 請求頭中提取 HTTP 的 User-Agent:

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

    通過?egrep?可以同時提取User-Agent 和主機名(或其他頭文件):

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

    8.2 抓取 HTTP GET 和 POST 請求

    抓取 HTTP GET 請求包:

    $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'# or$ tcpdump -vvAls0 | grep 'GET'

    可以抓取 HTTP POST 請求包:

    $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'# or $ tcpdump -vvAls0 | grep 'POST'

    注意:該方法不能保證抓取到 HTTP POST 有效數(shù)據(jù)流量,因為一個 POST 請求會被分割為多個 TCP 數(shù)據(jù)包。

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

    找出一段時間內(nèi)發(fā)包最多的 IP,或者從一堆報文中找出發(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?: 排序并計數(shù)
    • sort -nr?: 按照數(shù)值大小逆向排序

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

    DNS 的默認端口是 53,因此可以通過端口進行過濾

    $ tcpdump -i any -s0 port 53

    8.5 切割 pcap 文件

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

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

    這些文件的命名為?capture-{1-24}.pcap,24 小時之后,之前的文件就會被覆蓋。

    8.6 提取 HTTP POST 請求中的密碼

    從 HTTP POST 請求中提取密碼和主機名:

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

    8.7 提取 HTTP 請求的 URL

    提取 HTTP 請求的主機名和路徑:

    $ 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 進行分析

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

    還有一種更高效的方法,可以通過 ssh 連接將抓取到的數(shù)據(jù)實時發(fā)送給 Wireshark 進行分析。以 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ù):

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

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

    9. 參考文章

  • FreeBSD Manual Pages About tcpdump
  • Linux tcpdump命令詳解
  • 一份快速實用的 tcpdump 命令參考手冊
  • 超詳細的網(wǎng)絡(luò)抓包神器 tcpdump 使用指南
  • [譯]tcpdump 示例教程
  • [英]tcpdump 示例教程
  • 總結(jié)

    以上是生活随笔為你收集整理的tcpdump详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。