表达式的组合规则
tcpdump 的过滤表达式由 BPF 语法构成,逻辑运算符优先级固定:not 最高,其次 and,最后 or。这条优先级是把条件写错的主要来源——port 80 or port 443 and host 10.0.0.5 的实际含义与直觉不同。表达式里出现括号时必须整段用单引号包裹,否则 shell 会先把括号吃掉。
基本信息
| 适用平台 | Linux(tcpdump 需 root 或 CAP_NET_RAW);语法与 Wireshark 捕获过滤器一致 |
|---|---|
| 优先级 | not 最高,其次 and,最后 or;不确定就加括号 |
| 引号规则 | 整段表达式用单引号包裹,内部不要再套双引号 |
| 常用限定词 | host / net / port / portrange / src / dst / tcp[tcpflags] |
| 验证习惯 | 复杂表达式先加 -c 5 试跑,确认语法与命中量 |
典型使用场景
- 只抓某个主机的 Web 流量:host 与 (port 80 or port 443) 组合
- 排除自己的 SSH 会话,避免抓包终端被自身流量刷屏
- 只抓数据库方向的包:按目的端口区分出站与入站
- 按网段聚合:src net 10.0.0.0/24 限定整个办公网
- 按 TCP 标志位筛选:只抓 SYN 判断连接是否发起
组合示例
组合示例
sudo tcpdump -nn -i eth0 'host 10.0.0.5 and (port 80 or port 443)' # 括号必须加,否则语义改变
sudo tcpdump -nn -i eth0 'tcp and not port 22 and not port 443' # 排除管理与会话端口,避免刷屏
sudo tcpdump -nn -i eth0 '(dst port 3306 or dst port 5432) and src net 10.0.0.0/24' # 只看出向数据库流量
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' # 只看首次 SYN
sudo tcpdump -nn -i eth0 'host 10.0.0.5 and not port 22' -c 5 # 先小样本验证表达式
# 脚本里用 not 代替 !,避开交互式 shell 的历史展开运算符与写法要点
| 要点 | 说明 | 易错表现 |
|---|---|---|
| 优先级 | not > and > or | 漏括号导致条件被放宽或收窄 |
| 括号引号 | 整段表达式用单引号包裹 | shell 先解析括号,tcpdump 收到残缺表达式 |
| 否定写法 | 用 not,脚本里不要用 ! | 交互式 bash 中 ! 触发历史展开 |
| 限定词 | host/net/port/portrange 可加 src/dst | 写成 src 10.0.0.5 缺关键字直接报语法错误 |
| 标志位 | tcp[tcpflags] & tcp-syn != 0 | 写成 tcp-syn 单独使用无意义 |
表达式越复杂越要先用 -c 5 试跑并观察命中数量:命中为 0 说明条件写窄了,命中过多说明条件失效,两种情况都能在正式抓取前发现。
把常用表达式固化成脚本参数:长期排查的现场(如只排除管理端口、只看某个网段到数据库)写进封装脚本后,可避免每次重新推导优先级与引号规则。