tcpdump抓包分析
Tcpdump网络/命令行抓包工具
tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息
# tcpdump安装
apt-get install tcpdump
# 版本查看
tcpdump --h
1. tcpdump常用参数
| 参数 | 含义 |
|---|---|
| -a | 将网络地址和广播地址转变成名字 |
| -c | 在收到指定的包的数目后,tcpdump就会停止 ; |
| -d | 将匹配信息包的代码以人们能够理解的汇编格式给出;以可阅读的格式输出 |
| -dd | 将匹配信息包的代码以c语言程序段的格式给出; |
| -ddd | 将匹配信息包的代码以十进制的形式给出 |
| -e | 在输出行打印出数据链路层的头部信息; |
| -f | 将外部的Internet地址以数字的形式打印出来 |
| -I | 使标准输出变为缓冲行形式; |
| -n | 直接显示IP地址,不显示名称; |
| -nn | 端口名称显示为数字形式,不显示名称 |
| -t | 在输出的每一行不打印时间戳; |
| -v | 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息; |
| -vv | 输出详细的报文信息; |
| -F | 从指定的文件中读取表达式,忽略其它的表达式 |
| -i | 指定监听的网络接口; |
| -r | 从指定的文件中读取包(这些包一般通过-w选项产生); |
| -w | 直接将包写入文件中,并不分析和打印出来 ; |
| -T | 将监听到的包直接解释为指定的类型的报文,常见的类型有rp (远程过程调用)和snmp(简单 网络管理协议;) |
2. 常用使用参数选项
2.1 截获主机收到和发出的所有数据包
# 基础格式:时间 数据包类型 源IP 端口/协议 > 目标IP 端口/协议 协议详细信息
# tcpdump
17:25:41.303610 IP 172.19.0.48.60415 > dns.google.domain: 63411+ PTR? 230.12.19.172.in-addr.arpa. (44)
2.2 指定抓包数量
# ping jwgod.com
# tcpdump -c 2
17:32:58.860836 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25507, seq 31, length 64
17:32:58.861387 IP 172.19.0.48.55842 > dns.google.domain: 8121+ PTR? 153.108.199.185.in-addr.arpa. (46)
17:32:58.910778 IP dns.google.domain > 172.19.0.48.55842: 8121 1/0/0 PTR cdn-185-199-108-153.github.com. (90)
17:32:58.910955 IP 172.19.0.48.36070 > dns.google.domain: 32272+ PTR? 48.0.19.172.in-addr.arpa. (42)
17:32:58.912340 IP cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25507, seq 31, length 64
17:32:59.862496 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25507, seq 32, length 64
2.3 将抓包信息写入文件 -w
# tcpdump -c 10 -w tcpdump_test.log
备注:保存的文件不是文本格式,不能直接查看。tcpdump保存的文件的格式是几乎所有主流的抓包工具软件都可以读取。所以可以使用更易读的图形界面工具来查看记录文件
2.4 读取记录文件 -r
# tcpdump -r tcpdump_test.log
2.5 打印出所有可工作的接口 -D
# tcpdump -D
1.eth0 [Up, Running]
2.lo [Up, Running, Loopback]
3.any (Pseudo-device that captures on all interfaces) [Up, Running]
4.bluetooth-monitor (Bluetooth Linux Monitor) [none]
5.nflog (Linux netfilter log (NFLOG) interface) [none]
6.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]
# 其中网卡为eth0
2.6 指定监控的网卡 -i
# tcpdump -i eth0
备注:如果不指定网卡,默认tcpdump只会监视第一个网络接口,一般是eth0
2.7 显示更详细的数据包信息 -v -vv
# tcpdump -i eth0 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:42:48.251299 IP (tos 0x0, ttl 64, id 23778, offset 0, flags [DF], proto ICMP (1), length 84)
172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25517, seq 367, length 64
17:42:48.251903 IP (tos 0x0, ttl 64, id 45769, offset 0, flags [DF], proto UDP (17), length 74)
172.19.0.48.56590 > dns.google.domain: 21380+ PTR? 153.108.199.185.in-addr.arpa. (46)
17:42:48.302119 IP (tos 0x0, ttl 51, id 5314, offset 0, flags [none], proto ICMP (1), length 84)
cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25517, seq 367, length 64
# 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
# tcpdump -i eth0 -vv
# 输出详细的报文信息;
2.8 不使用域名反解 -n
# 使用-n后,tcpdump会直接显示IP地址,不会显示域名
# tcpdump -i eth0 -n
17:49:01.954428 IP 172.19.0.48 > 185.199.108.153: ICMP echo request, id 25517, seq 740, length 64
17:49:02.005387 IP 185.199.108.153 > 172.19.0.48: ICMP echo reply, id 25517, seq 740, length 64
17:49:02.954617 IP 172.19.0.48 > 185.199.108.153: ICMP echo request, id 25517, seq 741, length 64
2.9 增加抓包时间戳 -tttt选项
# tcpdump -i eth0 -tttt
2024-07-18 17:53:02.409496 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25517, seq 980, length 64
2024-07-18 17:53:02.409876 IP 172.19.0.48.38224 > dns.google.domain: 9234+ PTR? 153.108.199.185.in-addr.arpa. (46)
2024-07-18 17:53:02.460298 IP cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25517, seq 980, length 64
备注:时间戳信息的显示格式:hh:mm:ss.frac (nt: 小时:分钟:秒.)
3. 条件过滤
3.1 过滤–指定需要抓取的协议
备注:tcpdump可以只抓某种协议的包,支持指定以下协议:「ip,ip6,arp,tcp,udp,wlan」等
# tcpdump udp
17:59:19.899371 IP 172.19.0.1.50523 > 239.255.255.250.1900: UDP, length 175
17:59:20.906469 IP 172.19.0.1.50523 > 239.255.255.250.1900: UDP, length 175
# tcpdump icmp
18:00:04.209766 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25517, seq 1401, length 64
18:00:04.260576 IP cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25517, seq 1401, length 64
# tcpdump tcp
# tcpdump arp
3.2 过滤–指定协议的端口号
备注:使用port参数,用于指定端口号。
# tcpdump tcp port 80
备注:使用portrange参数,用于指定端口范围。
# tcpdump tcp portrange 1-1024
3.3 过滤–指定源与目标
备注:
src 表示源。
dst 表示目标。
# tcpdump src port 8080
# tcpdump dst port 80
3.4 过滤–指定特定主机的消息包
备注:若使用了host参数使用了计算机名或域名。例tcpdump host jwgod.com ,则无法再使用-n选项
# tcpdump host jwgod.com
3.5 过滤–指定数据包大小
备注:使用greater(大于)与less(小于)可以指定数据包大小的范围。
# 只抓取大于1000字节的数据包
# tcpdump greater 1000
# 只抓取小于10字节的数据包
# tcpdump less 10
4. 逻辑表达式
4.1 逻辑与
备注:逻辑与关系,使用and
# tcpdump tcp and host 192.168.64.11
# tcpdump tcp and src 192.168.64.11 and port 8080
4.2 逻辑或
备注:逻辑或关系,使用or
# tcpdump host 192.168.64.11 or 192.168.64.12
4.3 逻辑非
备注:逻辑非关系,使用not,也可以使用 !,若使用 ! 必须与其后面的字符隔开一个空格
# tcpdump not tcp port 22
# tcpdump ! tcp port 22
4.4 括号
备注:括号需要使用在引号内,或转意使用。否则会报错
# 抓取非22端口,且主机为192.168.64.11 和 192.168.64.12的TCP数据包
# tcpdump not tcp port 22 and host 192.168.64.11or192.168.64.12
# tcpdump "not tcp port 22 and host (192.168.64.11 or 192.168.64.12)"
# tcpdump not tcp port 22 and host "(192.168.64.11 or 192.168.64.12)"
5. 其他使用实例
5.1 打印所有进入或离开jwgod.com的数据包
# tcpdump host jwgod.com
5.2 截获主机192.168.64.11 和主机192.168.64.12 或192.168.64.13的通信
# tcpdump host 192.168.64.11 and (192.168.64.12 or 192.168.64.13 )
5.3 想要获取主机192.168.64.11除了和主机192.168.64.12之外所有主机通信的ip包
# tcpdump ip host 192.168.64.11 and ! 192.168.64.12
5.4 监视所有送到主机hostname的数据包
# tcpdump -i eth0 dst host hostname
5.5 获取主机192.168.64.11接收或发出的telnet包
# 23为telnet的端口
# tcpdump tcp port 23 and host 92.168.64.11
5.6 监视本机的udp 123 端口
# 123 为ntp的服务端口
# tcpdump udp port 123
5.7 使用tcpdump抓取HTTP包
# tcpdump -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854
备注:
0x4745 为"GET"前两个字母"GE",
0x4854 为"HTTP"前两个字母"HT"。
tcpdump 对截获的数据并没有进行彻底解码,数据包内的大部分内容是使用十六进制的形式直接打印输出的,显然这不利于分析网络故障,通常的解决办法是先使用带-w参数的tcpdump 截获数据并保存到文件中,然后再使用其他程序(如Wireshark)进行解码分析。当然也应该定义过滤规则,以避免捕获的数据包填满整个硬盘
6. 查看数据包完整内容
tcpdump默认不显示数据包的详细内容
6.1 使用-A参数能以ASCII码显示数据包
# 只抓取1个数据包,并显示其内容。
# tcpdump -c 1 -A
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:24:55.217307 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25535, seq 629, length 64
E..TP.@.@..d...0..l....Sc..uw..f.....P...................... !"#$%&'()*+,-./01234567
1 packet captured
30 packets received by filter
0 packets dropped by kernel
6.2 使用-X参数能16进制数与ASCII码共同显示数据包
# 只抓取1个数据包,并显示其内容。
# tcpdump -c 1 -X
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:25:46.290934 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25535, seq 680, length 64
0x0000: 4500 0054 5a7a 4000 4001 0d8b ac13 0030 E..TZz@.@......0
0x0010: b9c7 6c99 0800 2f01 63bf 02a8 aaed 9866 ..l.../.c......f
0x0020: 0000 0000 5c70 0400 0000 0000 1011 1213 ....\p..........
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
0x0050: 3435 3637 4567
1 packet captured
17 packets received by filter
0 packets dropped by kernel
7. tcpdump 与 wireshark
通过Tcpdump抓取的数据包分析比较麻烦,要想很方便的分析数据包, 我们可以用Tcpdump + Wireshark 的完美组合实现:在 Linux 里抓包,然后在Windows 里分析包,保存数据包为wireshark能识别的文件
# tcpdump tcp -i eth0 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.64.0/24 -w ./target.cap
| 参数 | 含义 |
|---|---|
| tcp | ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型 |
| -i eth0 | 只抓经过接口eth0的包 |
| -t | 不显示时间戳 |
| -s 0 | 抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包 |
| -c 100 | 只抓取100个数据包 |
| dst port ! 22 | 不抓取目标端口是22的数据包 |
| src net 192.168.64.0/24 | 数据包的源网络地址为192.168.1.0/24 |
| -w ./target.cap | 保存成cap文件,方便用ethereal(即wireshark)分析 |
wireshark安装
下载地址:https://2.na.dl.wireshark.org/win64/Wireshark-4.2.6-x64.exe
# 抓包
for i in `seq 1000000` ; do curl https://open.youzanyun.com/auth/token; echo \ $i; sleep 1;done
tcpdump -XvvennSs 0 -i ens18 host open.youzanyun.com -w tcpdump_test-ok.cap
三次握手失败

三次握手成功

Flags 标识符
使用 tcpdump 抓包后,会遇到的 TCP 报文 Flags,有以下几种:
- `[S]` : SYN(开始连接)
- `[P]` : PSH(推送数据)
- `[F]` : FIN (结束连接)
- `[R]` : RST(重置连接)
- `[.]` : 没有 Flag (意思是除上面四种类型外的其他情况,有可能是 ACK 也有可能是 URG)
8. 抓包实战应用例子
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 有效数据流量,因为一个 POST 请求会被分割为多个 TCP 数据包
8.3 找出发包数最多的 IP
# 找出一段时间内发包最多的 IP,或者从一堆报文中找出发包最多的 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: 排序并计数
- sort -nr: 按照数值大小逆向排序
8.4 抓取 DNS 请求和响应
# DNS 的默认端口是 53,因此可以通过端口进行过滤
# tcpdump -i any -s0 port 53
8.5 切割 pcap 文件
# 当抓取大量数据并写入文件时,可以自动切割为多个大小相同的文件。例如,下面的命令表示每 3600 秒创建一个新文件 `capture-(hour).pcap`,每个文件大小不超过 `200*1000000` 字节:
# 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 有效数据包
# 抓取 80 端口的 HTTP 有效数据包,排除 TCP 连接建立过程的数据包(SYN / FIN / ACK):
# tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
8.9 结合 Wireshark 进行分析
# 通常 Wireshark(或 tshark)比 tcpdump 更容易分析应用层协议。一般的做法是在远程服务器上先使用 tcpdump 抓取数据并写入文件,然后再将文件拷贝到本地工作站上用 Wireshark 分析。
# 还有一种更高效的方法,可以通过 ssh 连接将抓取到的数据实时发送给 Wireshark 进行分析。以 MacOS 系统为例,可以通过 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 协议,可以使用下面的命令:
# ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - port 53' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -
-c 选项用来限制抓取数据的大小。如果不限制大小,就只能通过 ctrl-c 来停止抓取,这样一来不仅关闭了 tcpdump,也关闭了 wireshark。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 悩姜!


