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 —— 源或目标端口是 80
  • src port 443 —— 仅源端口是 443
  • tcp / 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 过滤表达式分类 过滤表达式 基于网络层 基于传输层 基于应用层/逻辑 host net ip/icmp port tcp/udp tcpflags and/or/not 分组括号 协议字段偏移 提示:从左到右选择匹配的表达式,组合时注意用括号保证优先级

我曾经踩过的坑:在生产环境用 tcpdump -i any port 12345 抓包,结果发现抓到的包全带 VLAN 标签,链路层头部多出 4 字节,导致后面的 TCP payload 偏移解析错误。原因是 -i any 会先捕获裸链路层包,而 -i eth0 则自动剥离 VLAN。从那以后,我抓包必先确认接口是不是虚拟设备。

实战组合拳:快速定位异常

下面给你几个我日常排查时高频使用的组合,直接复制就能用。

  1. 查看某个 IP 的进出流量
tcpdump -i eth0 -nn host 192.168.1.100
  1. 抓 HTTP 请求与响应内容
tcpdump -i eth0 -A -nn tcp port 80 and not arp
  1. 只抓三次握手的 SYN 包
tcpdump -i eth0 -c 10 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'
  1. 回放之前保存的 pcap 文件,过滤出 DNS 查询
tcpdump -r dump.pcap -nn udp port 53

你看,每一条命令都像是给流量上了「精准滤镜」。不用抓到几万条流量,再手动翻找。嗯,这就是 tcpdump 的魅力。

一个小建议:如果你刚开始用,可以先在测试机试试 tcpdump -i lo -c 5 -nn 看本地回环流量。这样不会干扰其他同事,也不会误抓敏感数据。