tcpdump 入门:基本语法、常见选项与过滤表达式
做网络抓包,tcpdump 几乎是我工具箱里最趁手的家伙。你想想看,一个命令行工具,没图形界面,但几乎所有 Linux 系统自带,从服务器到路由器,从嵌入式设备到 Docker 容器,它都能用。今天我就带你把它最核心的部分捋清楚。
基本语法
tcpdump 的调用方式并不复杂。它的骨架就一句话:
tcpdump [选项] [过滤表达式]
说白了就是:选好参数,然后告诉它你想看什么流量。
如果不加任何选项,默认会监听第一块非 loopback 网卡,抓取所有包。嗯,这样可能会撑爆终端。我建议你每次用之前都先确认接口名。
常见选项
我个人习惯把常用选项按用途分成三类:网络接口选择、抓包控制、输出格式。下面这个表格基本涵盖了日常抓包够用的所有选项。
| 选项 | 作用 | 备注 |
|---|---|---|
-i eth0 |
指定监听的网卡 | 可以用 -i any 捕获所有接口 |
-c 100 |
抓取 100 个包后停止 | 避免数据风暴 |
-s 0 |
抓取完整的数据包(默认 262144 字节) | 一般不用改 |
-n |
不进行 DNS 解析 | 显示 IP 而非域名 |
-nn |
同时不转换端口名 | 直接显示端口数字 |
-v / -vv / -vvv |
增加输出详细程度 | -v 够用,-vvv 几乎用于调试协议细节 |
-w file.pcap |
将原始包写入文件 | 配合 -r file.pcap 回放 |
-X |
以 hex 和 ASCII 显示包内容 | 排查应用层问题时极有用 |
-A |
仅以 ASCII 显示包内容 | 适合 HTTP 协议的裸字符串 |
-e |
显示链路层头部信息 | 比如 MAC 地址、VLAN 标签 |
提个醒:抓包完成后,记得用 Ctrl+C 中断。但如果你提前知道要抓多少包,-c 选项能让它自动退出,省得你盯着终端不敢动。
过滤表达式:真正的核心
tcpdump 的过滤能力才是它和普通 tcpdump -i eth0 的区别。过滤表达式用的是「伯克利包过滤」语法,说白了就是一组逻辑条件,让抓包工具只留下你关心的流量。
我早期用 tcpdump 的时候,经常被满屏幕的 ARP 包刷屏。后来学会表达式,世界清净多了。下面我把表达式按照最佳实践分成几个大类。
1. 基于网络层:IP、子网、协议
host 192.168.1.1—— 只抓源或目标是 192.168.1.1 的包src net 10.0.0.0/8—— 源地址属于 10 网段dst net 172.16.0.0/12—— 目标地址属于 172.16 网段ip—— 只抓 IP 包(过滤掉 ARP、RARP 等)icmp—— 只抓 ping 包
2. 基于传输层:端口、TCP 标志位
port 80—— 源或目标端口是 80src port 443—— 仅源端口是 443tcp/udp—— 指定传输层协议tcp[tcpflags] & tcp-syn != 0—— 抓 SYN 包
为什么我要单独拎出 TCP 标志位?我在项目里有一次排查「握手超时」,结果发现 SYN 包根本没发出去。用 tcp[tcpflags] & tcp-syn != 0 过滤后,一眼看到网卡根本没发,最后定位是路由表配置错了。
3. 组合表达式:逻辑运算
and/or/not(或写作&&||!)- 例如:
host 10.0.0.1 and port 443 - 例如:
tcp and not port 22—— 过滤掉 SSH 流量
记得多用括号分组,否则优先级可能和你直觉不符。我曾经盯着一个 tcp and port 80 or 443 的抓包结果发愣——它抓了所有 80 端口的 TCP 包 + 所有 443 端口的包(非 TCP 也进来了)。正确的写法是 tcp and (port 80 or port 443)。
重点记忆:过滤表达式按顺序从左到右执行,但 and 优先级高于 or,所以该加括号时别偷懒。
过滤表达式知识图谱
下面这张图把常见过滤条件的层级关系整理出来了。你可以把它当成速查指南。
我曾经踩过的坑:在生产环境用 tcpdump -i any port 12345 抓包,结果发现抓到的包全带 VLAN 标签,链路层头部多出 4 字节,导致后面的 TCP payload 偏移解析错误。原因是 -i any 会先捕获裸链路层包,而 -i eth0 则自动剥离 VLAN。从那以后,我抓包必先确认接口是不是虚拟设备。
实战组合拳:快速定位异常
下面给你几个我日常排查时高频使用的组合,直接复制就能用。
- 查看某个 IP 的进出流量
tcpdump -i eth0 -nn host 192.168.1.100
- 抓 HTTP 请求与响应内容
tcpdump -i eth0 -A -nn tcp port 80 and not arp
- 只抓三次握手的 SYN 包
tcpdump -i eth0 -c 10 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'
- 回放之前保存的 pcap 文件,过滤出 DNS 查询
tcpdump -r dump.pcap -nn udp port 53
你看,每一条命令都像是给流量上了「精准滤镜」。不用抓到几万条流量,再手动翻找。嗯,这就是 tcpdump 的魅力。
一个小建议:如果你刚开始用,可以先在测试机试试 tcpdump -i lo -c 5 -nn 看本地回环流量。这样不会干扰其他同事,也不会误抓敏感数据。