1. 程式人生 > >超詳細的網路抓包神器 tcpdump 使用指南

超詳細的網路抓包神器 tcpdump 使用指南

> 原文連結:[Tcpdump 示例教程](https://fuckcloudnative.io/posts/tcpdump-examples/) > 本文主要內容翻譯自[《Tcpdump Examples》](https://hackertarget.com/tcpdump-examples/)。 `tcpdump` 是一款強大的網路抓包工具,它使用 `libpcap` 庫來抓取網路資料包,這個庫在幾乎在所有的 Linux/Unix 中都有。熟悉 tcpdump 的使用能夠幫助你分析除錯網路資料,本文將通過一個個具體的示例來介紹它在不同場景下的使用方法。不管你是系統管理員,程式設計師,雲原生工程師還是 yaml 工程師,掌握 tcpdump 的使用都能讓你如虎添翼,升職加薪。 ## 1. 基本語法和使用方法 `tcpdump` 的常用引數如下: ```bash $ tcpdump -i eth0 -nn -s0 -v port 80 ``` + **-i** : 選擇要捕獲的介面,通常是乙太網卡或無線網絡卡,也可以是 `vlan` 或其他特殊介面。如果該系統上只有一個網路介面,則無需指定。 + **-nn** : 單個 n 表示不解析域名,直接顯示 IP;兩個 n 表示不解析域名和埠。這樣不僅方便檢視 IP 和埠號,而且在抓取大量資料時非常高效,因為域名解析會降低抓取速度。 + **-s0** : tcpdump 預設只會擷取前 `96` 位元組的內容,要想擷取所有的報文內容,可以使用 `-s number`, `number` 就是你要擷取的報文位元組數,如果是 0 的話,表示擷取報文全部內容。 + **-v** : 使用 `-v`,`-vv` 和 `-vvv` 來顯示更多的詳細資訊,通常會顯示更多與特定協議相關的資訊。 + `port 80` : 這是一個常見的埠過濾器,表示僅抓取 `80` 埠上的流量,通常是 HTTP。 額外再介紹幾個常用引數: + **-p** : 不讓網路介面進入混雜模式。預設情況下使用 tcpdump 抓包時,會讓網路介面進入混雜模式。一般計算機網絡卡都工作在非混雜模式下,此時網絡卡只接受來自網路埠的目的地址指向自己的資料。當網絡卡工作在混雜模式下時,網絡卡將來自介面的所有資料都捕獲並交給相應的驅動程式。如果裝置接入的交換機開啟了混雜模式,使用 `-p` 選項可以有效地過濾噪聲。 + **-e** : 顯示資料鏈路層資訊。預設情況下 tcpdump 不會顯示資料鏈路層資訊,使用 `-e` 選項可以顯示源和目的 MAC 地址,以及 VLAN tag 資訊。例如: ```bash $ tcpdump -n -e -c 5 not ip6 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes 18:27:53.619865 24:5e:be:0c:17:af > 00:e2:69:23:d3:3b, ethertype IPv4 (0x0800), length 1162: 192.168.100.20.51410 > 180.176.26.193.58695: Flags [.], seq 2045333376:2045334484, ack 3398690514, win 751, length 1108 18:27:53.626490 00:e2:69:23:d3:3b > 24:5e:be:0c:17:af, ethertype IPv4 (0x0800), length 68: 220.173.179.66.36017 > 192.168.100.20.51410: UDP, length 26 18:27:53.626893 24:5e:be:0c:17:af > 00:e2:69:23:d3:3b, ethertype IPv4 (0x0800), length 1444: 192.168.100.20.51410 > 220.173.179.66.36017: UDP, length 1402 18:27:53.628837 00:e2:69:23:d3:3b > 24:5e:be:0c:17:af, ethertype IPv4 (0x0800), length 1324: 46.97.169.182.6881 > 192.168.100.20.59145: Flags [P.], seq 3058450381:3058451651, ack 14349180, win 502, length 1270 18:27:53.629096 24:5e:be:0c:17:af > 00:e2:69:23:d3:3b, ethertype IPv4 (0x0800), length 54: 192.168.100.20.59145 > 192.168.100.1.12345: Flags [.], ack 3058451651, win 6350, length 0 5 packets captured ``` ### 顯示 ASCII 字串 `-A` 表示使用 `ASCII` 字串列印報文的全部資料,這樣可以使讀取更加簡單,方便使用 `grep` 等工具解析輸出內容。`-X` 表示同時使用十六進位制和 `ASCII` 字串列印報文的全部資料。這兩個引數不能一起使用。例如: ```bash $ tcpdump -A -s0 port 80 ``` ### 抓取特定協議的資料 後面可以跟上協議名稱來過濾特定協議的流量,以 UDP 為例,可以加上引數 udp 或 `protocol 17`,這兩個命令意思相同。 ```bash $ tcpdump -i eth0 udp $ tcpdump -i eth0 proto 17 ``` 同理,tcp 與 `protocol 6` 意思相同。 ### 抓取特定主機的資料 使用過濾器 `host` 可以抓取特定目的地和源 IP 地址的流量。 ```bash $ tcpdump -i eth0 host 10.10.1.1 ``` 也可以使用 `src` 或 `dst` 只抓取源或目的地: ```bash $ tcpdump -i eth0 dst 10.10.1.20 ``` ### 將抓取的資料寫入檔案 使用 tcpdump 擷取資料報文的時候,預設會列印到螢幕的預設輸出,你會看到按照順序和格式,很多的資料一行行快速閃過,根本來不及看清楚所有的內容。不過,tcpdump 提供了把擷取的資料儲存到檔案的功能,以便後面使用其他圖形工具(比如 wireshark,Snort)來分析。 `-w` 選項用來把資料報文輸出到檔案: ```bash $ tcpdump -i eth0 -s0 -w test.pcap ``` ### 行緩衝模式 如果想實時將抓取到的資料通過管道傳遞給其他工具來處理,需要使用 `-l` 選項來開啟行緩衝模式(或使用 `-c` 選項來開啟資料包緩衝模式)。使用 `-l` 選項可以將輸出通過立即傳送給其他命令,其他命令會立即響應。 ```bash $ tcpdump -i eth0 -s0 -l port 80 | grep 'Server:' ``` ### 組合過濾器 過濾的真正強大之處在於你可以隨意組合它們,而連線它們的邏輯就是常用的 `與/AND/&&` 、 `或/OR/||` 和 `非/not/!`。 ```bash and or && or or || not or ! ``` ## 2. 過濾器 關於 tcpdump 的過濾器,這裡有必要單獨介紹一下。 機器上的網路報文數量異常的多,很多時候我們只關係和具體問題有關的資料報(比如訪問某個網站的資料,或者 icmp 超時的報文等等),而這些資料只佔到很小的一部分。把所有的資料擷取下來,從裡面找到想要的資訊無疑是一件很費時費力的工作。而 tcpdump 提供了靈活的語法可以精確地擷取關心的資料報,簡化分析的工作量。這些選擇資料包的語句就是過濾器(filter)! ### Host 過濾器 Host 過濾器用來過濾某個主機的資料報文。例如: ```bash $ tcpdump host 1.2.3.4 ``` 該命令會抓取所有發往主機 `1.2.3.4` 或者從主機 `1.2.3.4` 發出的流量。如果想只抓取從該主機發出的流量,可以使用下面的命令: ```bash $ tcpdump src host 1.2.3.4 ``` ### Network 過濾器 Network 過濾器用來過濾某個網段的資料,使用的是 [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) 模式。可以使用四元組(x.x.x.x)、三元組(x.x.x)、二元組(x.x)和一元組(x)。四元組就是指定某個主機,三元組表示子網掩碼為 `255.255.255.0`,二元組表示子網掩碼為 `255.255.0.0`,一元組表示子網掩碼為 `255.0.0.0`。例如, 抓取所有發往網段 `192.168.1.x` 或從網段 `192.168.1.x` 發出的流量: ```bash $ tcpdump net 192.168.1 ``` 抓取所有發往網段 `10.x.x.x` 或從網段 `10.x.x.x` 發出的流量: ```bash $ tcpdump net 10 ``` 和 Host 過濾器一樣,這裡也可以指定源和目的: ```bash $ tcpdump src net 10 ``` 也可以使用 CIDR 格式: ```bash $ tcpdump src net 172.16.0.0/12 ``` ### Proto 過濾器 Proto 過濾器用來過濾某個協議的資料,關鍵字為 `proto`,可省略。proto 後面可以跟上協議號或協議名稱,支援 `icmp`, `igmp`, `igrp`, `pim`, `ah`, `esp`, `carp`, `vrrp`, `udp `和 `tcp`。因為通常的協議名稱是保留欄位,所以在於 proto 指令一起使用時,必須根據 shell 型別使用一個或兩個反斜槓(/)來轉義。Linux 中的 shell 需要使用兩個反斜槓來轉義,MacOS 只需要一個。 例如,抓取 icmp 協議的報文: ```bash $ tcpdump -n proto \\icmp # 或者 $ tcpdump -n icmp ``` ### Port 過濾器 Port 過濾器用來過濾通過某個埠的資料報文,關鍵字為 `port`。例如: ```bash $ tcpdump port 389 ``` ## 3. 理解 tcpdump 的輸出 擷取資料只是第一步,第二步就是理解這些資料,下面就解釋一下 tcpdump 命令輸出各部分的意義。 ```bash 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 ``` 最基本也是最重要的資訊就是資料報的源地址/埠和目的地址/埠,上面的例子第一條資料報中,源地址 ip 是 `192.168.1.106`,源埠是 `56166`,目的地址是 `124.192.132.54`,目的埠是 `80`。 `>` 符號代表資料的方向。 此外,上面的三條資料還是 tcp 協議的三次握手過程,第一條就是 `SYN` 報文,這個可以通過 `Flags [S]` 看出。下面是常見的 TCP 報文的 Flags: - `[S]` : SYN(開始連線) - `[.]` : 沒有 Flag - `[P]` : PSH(推送資料) - `[F]` : FIN (結束連線) - `[R]` : RST(重置連線) 而第二條資料的 `[S.]` 表示 `SYN-ACK`,就是 `SYN` 報文的應答報文。 ## 4. 例子 下面給出一些具體的例子,每個例子都可以使用多種方法來獲得相同的輸出,你使用的方法取決於所需的輸出和網路上的流量。我們在排障時,通常只想獲取自己想要的內容,可以通過過濾器和 ASCII 輸出並結合管道與 grep、cut、awk 等工具來實現此目的。 例如,在抓取 HTTP 請求和響應資料包時,可以通過刪除標誌 `SYN/ACK/FIN` 來過濾噪聲,但還有更簡單的方法,那就是通過管道傳遞給 `grep`。在達到目的的同時,我們要選擇最簡單最高效的方法。下面來看例子。 ### 提取 HTTP 使用者代理 從 HTTP 請求頭中提取 HTTP 使用者代理: ```bash $ tcpdump -nn -A -s1500 -l | grep "User-Agent:" ``` 通過 `egrep` 可以同時提取使用者代理和主機名(或其他標頭檔案): ```bash $ tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host:' ``` ### 只抓取 HTTP GET 和 POST 流量 抓取 HTTP GET 流量: ```bash $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420' ``` 也可以抓取 HTTP POST 請求流量: ```bash $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354' ``` 注意:該方法不能保證抓取到 HTTP POST 有效資料流量,因為一個 POST 請求會被分割為多個 TCP 資料包。 上述兩個表示式中的十六進位制將會與 GET 和 POST 請求的 `ASCII` 字串匹配。例如,`tcp[((tcp[12:1] & 0xf0) >> 2):4]` 首先會[確定我們感興趣的位元組的位置](https://security.stackexchange.com/questions/121011/wireshark-tcp-filter-tcptcp121-0xf0-24)(在 TCP header 之後),然後選擇我們希望匹配的 4 個位元組。 ### 提取 HTTP 請求的 URL 提取 HTTP 請求的主機名和路徑: ```bash $ tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:" tcpdump: listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes POST /wp-login.php HTTP/1.1 Host: dev.example.com GET /wp-login.php HTTP/1.1 Host: dev.example.com GET /favicon.ico HTTP/1.1 Host: dev.example.com GET / HTTP/1.1 Host: dev.example.com ``` ### 提取 HTTP POST 請求中的密碼 從 HTTP POST 請求中提取密碼和主機名: ```bash $ tcpdump -s 0 -A -n -l | egrep -i "POST /|pwd=|passwd=|password=|Host:" tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes 11:25:54.799014 IP 10.10.1.30.39224 > 10.10.1.125.80: Flags [P.], seq 1458768667:1458770008, ack 2440130792, win 704, options [nop,nop,TS val 461552632 ecr 208900561], length 1341: HTTP: POST /wp-login.php HTTP/1.1 .....s..POST /wp-login.php HTTP/1.1 Host: dev.example.com .....s..log=admin&pwd=notmypassword&wp-submit=Log+In&redirect_to=http%3A%2F%2Fdev.example.com%2Fwp-admin%2F&testcookie=1 ``` ### 提取 Cookies 提取 `Set-Cookie`(服務端的 Cookie)和 `Cookie`(客戶端的 Cookie): ```bash $ tcpdump -nn -A -s0 -l | egrep -i 'Set-Cookie|Host:|Cookie:' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on wlp58s0, link-type EN10MB (Ethernet), capture size 262144 bytes Host: dev.example.com Cookie: wordpress_86be02xxxxxxxxxxxxxxxxxxxc43=admin%7C152xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxfb3e15c744fdd6; _ga=GA1.2.21343434343421934; _gid=GA1.2.927343434349426; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_86be654654645645645654645653fc43=admin%7C15275102testtesttesttestab7a61e; wp-settings-time-1=1527337439 ``` ### 抓取 ICMP 資料包 檢視網路上的所有 ICMP 資料包: ```bash $ tcpdump -n icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes 11:34:21.590380 IP 10.10.1.217 > 10.10.1.30: ICMP echo request, id 27948, seq 1, length 64 11:34:21.590434 IP 10.10.1.30 > 10.10.1.217: ICMP echo reply, id 27948, seq 1, length 64 11:34:27.680307 IP 10.10.1.159 > 10.10.1.1: ICMP 10.10.1.189 udp port 59619 unreachable, length 115 ``` ### 抓取非 ECHO/REPLY 型別的 ICMP 資料包 通過排除 echo 和 reply 型別的資料包使抓取到的資料包不包括標準的 `ping` 包: ```bash $ tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes 11:37:04.041037 IP 10.10.1.189 > 10.10.1.20: ICMP 10.10.1.189 udp port 36078 unreachable, length 156 ``` ### 抓取 SMTP/POP3 協議的郵件 可以提取電子郵件的正文和其他資料。例如,只提取電子郵件的收件人: ```bash $ tcpdump -nn -l port 25 | grep -i 'MAIL FROM\|RCPT TO' ``` ### 抓取 NTP 服務的查詢和響應 ```bash $ tcpdump dst port 123 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 21:02:19.112502 IP test33.ntp > 199.30.140.74.ntp: NTPv4, Client, length 48 21:02:19.113888 IP 216.239.35.0.ntp > test33.ntp: NTPv4, Server, length 48 21:02:20.150347 IP test33.ntp > 216.239.35.0.ntp: NTPv4, Client, length 48 21:02:20.150991 IP 216.239.35.0.ntp > test33.ntp: NTPv4, Server, length 48 ``` ### 抓取 SNMP 服務的查詢和響應 通過 SNMP 服務,滲透測試人員可以獲取大量的裝置和系統資訊。在這些資訊中,系統資訊最為關鍵,如作業系統版本、核心版本等。使用 SNMP 協議快速掃描程式 `onesixtyone`,可以看到目標系統的資訊: ```bash $ onesixtyone 10.10.1.10 public Scanning 1 hosts, 1 communities 10.10.1.10 [public] Linux test33 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 ``` 可以通過 tcpdump 抓取 `GetRequest` 和 `GetResponse`: ```bash $ tcpdump -n -s0 port 161 and udp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on wlp58s0, link-type EN10MB (Ethernet), capture size 262144 bytes 23:39:13.725522 IP 10.10.1.159.36826 > 10.10.1.20.161: GetRequest(28) .1.3.6.1.2.1.1.1.0 23:39:13.728789 IP 10.10.1.20.161 > 10.10.1.159.36826: GetResponse(109) .1.3.6.1.2.1.1.1.0="Linux testmachine 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64" ``` ### 切割 pcap 檔案 當抓取大量資料並寫入檔案時,可以自動切割為多個大小相同的檔案。例如,下面的命令表示每 3600 秒建立一個新檔案 `capture-(hour).pcap`,每個檔案大小不超過 `200*1000000` 位元組: ```bash $ tcpdump -w /tmp/capture-%H.pcap -G 3600 -C 200 ``` 這些檔案的命名為 `capture-{1-24}.pcap`,24 小時之後,之前的檔案就會被覆蓋。 ### 抓取 IPv6 流量 可以通過過濾器 `ip6` 來抓取 IPv6 流量,同時可以指定協議如 TCP: ```bash $ tcpdump -nn ip6 proto 6 ``` 從之前儲存的檔案中讀取 IPv6 UDP 資料報文: ```bash $ tcpdump -nr ipv6-test.pcap ip6 proto 17 ``` ### 檢測埠掃描 在下面的例子中,你會發現抓取到的報文的源和目的一直不變,且帶有標誌位 `[S]` 和 `[R]`,它們與一系列看似隨機的目標埠進行匹配。當傳送 `SYN` 之後,如果目標主機的埠沒有開啟,就會返回一個 `RESET`。這是 `Nmap` 等埠掃描工具的標準做法。 ```bash $ tcpdump -nn 21:46:19.693601 IP 10.10.1.10.60460 > 10.10.1.199.5432: Flags [S], seq 116466344, win 29200, options [mss 1460,sackOK,TS val 3547090332 ecr 0,nop,wscale 7], length 0 21:46:19.693626 IP 10.10.1.10.35470 > 10.10.1.199.513: Flags [S], seq 3400074709, win 29200, options [mss 1460,sackOK,TS val 3547090332 ecr 0,nop,wscale 7], length 0 21:46:19.693762 IP 10.10.1.10.44244 > 10.10.1.199.389: Flags [S], seq 2214070267, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0 21:46:19.693772 IP 10.10.1.199.389 > 10.10.1.10.44244: Flags [R.], seq 0, ack 2214070268, win 0, length 0 21:46:19.693783 IP 10.10.1.10.35172 > 10.10.1.199.1433: Flags [S], seq 2358257571, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0 21:46:19.693826 IP 10.10.1.10.33022 > 10.10.1.199.49153: Flags [S], seq 2406028551, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0 21:46:19.695567 IP 10.10.1.10.55130 > 10.10.1.199.49154: Flags [S], seq 3230403372, win 29200, options [mss 1460,sackOK,TS val 3547090334 ecr 0,nop,wscale 7], length 0 21:46:19.695590 IP 10.10.1.199.49154 > 10.10.1.10.55130: Flags [R.], seq 0, ack 3230403373, win 0, length 0 21:46:19.695608 IP 10.10.1.10.33460 > 10.10.1.199.49152: Flags [S], seq 3289070068, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0 21:46:19.695622 IP 10.10.1.199.49152 > 10.10.1.10.33460: Flags [R.], seq 0, ack 3289070069, win 0, length 0 21:46:19.695637 IP 10.10.1.10.34940 > 10.10.1.199.1029: Flags [S], seq 140319147, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0 21:46:19.695650 IP 10.10.1.199.1029 > 10.10.1.10.34940: Flags [R.], seq 0, ack 140319148, win 0, length 0 21:46:19.695664 IP 10.10.1.10.45648 > 10.10.1.199.5060: Flags [S], seq 2203629201, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0 21:46:19.695775 IP 10.10.1.10.49028 > 10.10.1.199.2000: Flags [S], seq 635990431, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0 21:46:19.695790 IP 10.10.1.199.2000 > 10.10.1.10.49028: Flags [R.], seq 0, ack 635990432, win 0, length 0 ``` ### 過濾 Nmap NSE 指令碼測試結果 本例中 Nmap NSE 測試指令碼 `http-enum.nse` 用來檢測 HTTP 服務的合法 URL。 在執行指令碼測試的主機上: ```bash $ nmap -p 80 --script=http-enum.nse targetip ``` 在目標主機上: ```bash $ tcpdump -nn port 80 | grep "GET /" GET /w3perl/ HTTP/1.1 GET /w-agora/ HTTP/1.1 GET /way-board/ HTTP/1.1 GET /web800fo/ HTTP/1.1 GET /webaccess/ HTTP/1.1 GET /webadmin/ HTTP/1.1 GET /webAdmin/ HTTP/1.1 ``` ### 抓取 DNS 請求和響應 向 Google 公共 DNS 發起的出站 `DNS` 請求和 A 記錄響應可以通過 tcpdump 抓取到: ```bash $ tcpdump -i wlp58s0 -s0 port 53 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on wlp58s0, link-type EN10MB (Ethernet), capture size 262144 bytes 14:19:06.879799 IP test.53852 > google-public-dns-a.google.com.domain: 26977+ [1au] A? play.google.com. (44) 14:19:07.022618 IP google-public-dns-a.google.com.domain > test.53852: 26977 1/0/1 A 216.58.203.110 (60) ``` ### 抓取 HTTP 有效資料包 抓取 80 埠的 HTTP 有效資料包,排除 TCP 連線建立過程的資料包(SYN / FIN / ACK): ```bash $ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' ``` ### 將輸出內容重定向到 Wireshark 通常 `Wireshark`(或 tshark)比 tcpdump 更容易分析應用層協議。一般的做法是在遠端伺服器上先使用 `tcpdump` 抓取資料並寫入檔案,然後再將檔案拷貝到本地工作站上用 `Wireshark` 分析。 還有一種更高效的方法,可以通過 ssh 連線將抓取到的資料實時傳送給 Wireshark 進行分析。以 MacOS 系統為例,可以通過 `brew cask install wireshark` 來安裝,然後通過下面的命令來分析: ```bash $ ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - not port 22' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i - ``` 例如,如果想分析 DNS 協議,可以使用下面的命令: ```bash $ ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - port 53' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i - ``` 抓取到的資料: ![](https://hugo-picture.oss-cn-beijing.aliyuncs.com/images/20200210170101.png) `-c` 選項用來限制抓取資料的大小。如果不限制大小,就只能通過 `ctrl-c` 來停止抓取,這樣一來不僅關閉了 tcpdump,也關閉了 wireshark。 ### 找出發包最多的 IP 找出一段時間內發包最多的 IP,或者從一堆報文中找出發包最多的 IP,可以使用下面的命令: ```bash $ tcpdump -nnn -t -c 200 | cut -f 1,2,3,4 -d '.' | sort | uniq -c | sort -nr | head -n 20 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes 200 packets captured 261 packets received by filter 0 packets dropped by kernel 108 IP 10.10.211.181 91 IP 10.10.1.30 1 IP 10.10.1.50 ``` + **cut -f 1,2,3,4 -d '.'** : 以 `.` 為分隔符,打印出每行的前四列。即 IP 地址。 + **sort | uniq -c** : 排序並計數 + **sort -nr** : 按照數值大小逆向排序 ### 抓取使用者名稱和密碼 本例將重點放在標準純文字協議上,過濾出於使用者名稱和密碼相關的報文: ```bash $ tcpdump port http or port ftp or port smtp or port imap or port pop3 or port telnet -l -A | egrep -i -B5 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|passwd=|password=|pass:|user:|username:|password:|login:|pass |user ' ``` ### 抓取 DHCP 報文 最後一個例子,抓取 DHCP 服務的請求和響應報文,67 為 DHCP 埠,68 為客戶機埠。 ```bash $ tcpdump -v -n port 67 or 68 tcpdump: listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes 14:37:50.059662 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328) 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:0c:xx:xx:xx:d5, length 300, xid 0xc9779c2a, Flags [none] Client-Ethernet-Address 00:0c:xx:xx:xx:d5 Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Request Requested-IP Option 50, length 4: 10.10.1.163 Hostname Option 12, length 14: "test-ubuntu" Parameter-Request Option 55, length 16: Subnet-Mask, BR, Time-Zone, Default-Gateway Domain-Name, Domain-Name-Server, Option 119, Hostname Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route NTP, Classless-Static-Route-Microsoft, Static-Route, Option 252 14:37:50.059667 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328) 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:0c:xx:xx:xx:d5, length 300, xid 0xc9779c2a, Flags [none] Client-Ethernet-Address 00:0c:xx:xx:xx:d5 Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Request Requested-IP Option 50, length 4: 10.10.1.163 Hostname Option 12, length 14: "test-ubuntu" Parameter-Request Option 55, length 16: Subnet-Mask, BR, Time-Zone, Default-Gateway Domain-Name, Domain-Name-Server, Option 119, Hostname Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route NTP, Classless-Static-Route-Microsoft, Static-Route, Option 252 14:37:50.060780 IP (tos 0x0, ttl 64, id 53564, offset 0, flags [none], proto UDP (17), length 339) 10.10.1.1.67 > 10.10.1.163.68: BOOTP/DHCP, Reply, length 311, xid 0xc9779c2a, Flags [none] Your-IP 10.10.1.163 Server-IP 10.10.1.1 Client-Ethernet-Address 00:0c:xx:xx:xx:d5 Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: ACK Server-ID Option 54, length 4: 10.10.1.1 Lease-Time Option 51, length 4: 86400 RN Option 58, length 4: 43200 RB Option 59, length 4: 75600 Subnet-Mask Option 1, length 4: 255.255.255.0 BR Option 28, length 4: 10.10.1.255 Domain-Name-Server Option 6, length 4: 10.10.1.1 Hostname Option 12, length 14: "test-ubuntu" T252 Option 252, length 1: 10 Default-Gateway Option 3, length 4: 10.10.1.1 ``` ## 5. 總結 本文主要介紹了 `tcpdump` 的基本語法和使用方法,並通過一些示例來展示它強大的過濾功能。將 tcpdump 與 wireshark 進行組合可以發揮更強大的功效,本文也展示瞭如何優雅順滑地結合 tcpdump 和 wireshark。如果你想了解更多的細節,可以檢視 tcpdump 的 `man` 手冊。