tcpdump 是 Linux/Unix 系统下最强大的命令行网络抓包工具,被誉为网络分析界的"瑞士军刀"。它能实时捕获流经网卡的数据包,是排查网络故障、分析协议交互和安全审计的必备利器。
📖 基础语法与常用选项
tcpdump 的基本命令格式为:tcpdump [选项] [过滤表达式]。
执行抓包通常需要 root 权限,或通过 sudo 执行。以下是一些最常用的选项:
| 选项 | 作用 | 示例 |
|---|---|---|
-i <接口> |
指定要监听的网络接口。 | tcpdump -i eth0 |
-i any |
监听所有网络接口。 | tcpdump -i any |
-c <数量> |
捕获指定数量的数据包后自动停止。 | tcpdump -c 10 |
-w <文件> |
将捕获的原始数据包保存到文件 (通常为 .pcap 格式)。 |
tcpdump -w capture.pcap |
-r <文件> |
读取并分析之前保存的数据包文件。 | tcpdump -r capture.pcap |
-n |
禁用IP地址到主机名的解析,直接显示IP,加快处理速度。 | tcpdump -n |
-nn |
同时禁用IP和端口号到服务名的解析(如显示80而非http)。 | tcpdump -nn |
-v/-vv/-vvv |
增加输出的详细程度。 | tcpdump -vv |
-s <长度> |
设置每个数据包的抓取长度(快照长度) 。-s 0 表示抓取完整数据包。 |
tcpdump -s 0 |
-A |
以 ASCII 格式显示每个数据包的内容。 | tcpdump -A |
-X |
以 十六进制和ASCII 混合格式显示数据包内容。 | tcpdump -X |
-e |
在输出行中显示链路层头部信息(如源/目的MAC地址)。 | tcpdump -e |
-D |
列出系统上所有可用的网络接口。 | tcpdump -D |
提示 :
-s 0在排查应用层问题时尤其重要,可以确保捕获到完整的数据载荷。但在高流量或长时间抓包时,为避免性能问题,建议根据分析目标设置合适的snaplen。
🎯 过滤表达式:精准捕获目标
过滤表达式是 tcpdump 的核心,能帮我们从海量数据包中精准定位目标。
1. 按主机、网络、端口过滤
- 主机:捕获与特定IP相关的所有流量。
bash
tcpdump host 192.168.1.100
- 源/目的主机:仅捕获源或目的为特定IP的流量。
bash
tcpdump src 192.168.1.100
tcpdump dst 192.168.1.100
- 网络:捕获整个子网的流量。
bash
tcpdump net 192.168.1.0/24
- 端口:捕获指定端口(如HTTP的80端口)的流量。
bash
tcpdump port 80
tcpdump src port 22
tcpdump dst port 443
2. 按协议过滤
直接指定协议名称即可。
bash
tcpdump tcp
tcpdump udp
tcpdump icmp
tcpdump arp
3. 使用逻辑运算符组合
使用 and、or、not 将多个条件组合,构建复杂过滤规则。
bash
# 捕获来自 192.168.1.100 且目标端口为 80 的流量
tcpdump "src host 192.168.1.100 and dst port 80"
# 捕获 80 或 443 端口的流量
tcpdump "port 80 or port 443"
# 排除 SSH 流量
tcpdump "not port 22"
4. 高级过滤:BPF语法
tcpdump 使用强大的伯克利包过滤(BPF) 语法,可以深入到数据包内部进行过滤-。
- 过滤TCP标志位 :例如,只抓取SYN包 -2或SYN-ACK包。
bash
# 仅捕获 SYN 包 (tcp[13] 是TCP头的第13个字节,值为2表示SYN标志)
tcpdump 'tcp[13] & 2 != 0'
# 仅捕获 SYN-ACK 包 (值为18表示SYN和ACK标志)
tcpdump 'tcp[13] == 18'
- 捕获HTTP GET请求 :通过匹配数据包内容中的
GET字符串(十六进制为0x47455420)。
bash
tcpdump -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'
📊 输出解读
一个典型的 tcpdump 输出行如下:
14:30:22.123456 IP 192.168.1.100.54321 > 192.168.1.200.80: Flags [P.], seq 1:100, ack 200, win 1000
-
14:30:22.123456:数据包捕获的时间戳。 -
IP:网络层协议类型。 -
192.168.1.100.54321 > 192.168.1.200.80:源地址.源端口 到 目的地址.目的端口。 -
Flags [P.]:TCP标志位 ,常见的有S(SYN),F(FIN),R(RST),P.(PUSH-ACK) 等。 -
seq 1:100:序列号及数据长度。 -
ack 200:确认号。 -
win 1000:窗口大小。
💡 实战技巧与场景
1. 必备技巧
-
列出可用网卡 :抓包前先用
tcpdump -D确认目标网卡名称。 -
始终使用
-n或-nn:避免DNS解析带来的延迟和干扰,让输出更清晰。 -
限制抓包数量 :测试时务必使用
-c选项,防止终端被刷屏。 -
善用
-s 0:确保捕获完整数据包,便于分析应用层数据。 -
保存原始数据 :将抓包结果保存为
.pcap文件,方便后续用 Wireshark 等工具进行图形化深度分析-。
2. 常见场景命令
- 分析HTTP通信:
bash
tcpdump -i eth0 -nn -A -s 0 'tcp port 80'
- 排查特定主机的网络问题:
bash
tcpdump -i eth0 -nn host 192.168.1.100
- 分析非标准端口服务:
bash
tcpdump -i eth0 -nn port 8080
- 检查DNS解析:
bash
tcpdump -i eth0 -nn 'udp port 53'
- 追踪Ping(ICMP)包:
bash
tcpdump -i eth0 -nn 'icmp'
- 查看三次握手过程:
bash
tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn) != 0'
🚀 高级用法与性能优化
-
流量方向控制 :使用
-Q选项指定只抓入站(in)、出站(out)或双向(inout)流量。 -
大文件自动分割 :使用
-C <文件大小>(单位MB)和-W <文件数量>选项,可实现抓包文件的自动分割与循环覆盖,非常适合长时间抓包。 -
实时写入磁盘 :使用
-U选项,让数据包实时写入文件,避免因缓冲区延迟导致数据丢失。
⚠️ 常见问题
-
为什么抓不到任何包?
-
检查是否使用了正确的网卡接口(
-i)。 -
确认是否有
root权限。 -
检查过滤表达式是否过于严格,排除了所有流量。
-
-
输出显示的是主机名而不是IP?
- 忘记加
-n或-nn参数了。
- 忘记加
-
抓包时系统变慢或丢包?
-
尝试减小快照长度(
-s)。 -
使用更精准的过滤表达式,减少不必要的数据包捕获。
-
将抓包结果写入本地文件系统(如
/tmp),而非网络存储。
-