← 全部笔记

tcpdump 抓包:先缩小范围,再开始看

2026-10-27 网络与协议 约 8 分钟

抓包最大的浪费不是不会看,是一上来就 tcpdump -i any 全量刷屏, 在几千行里找一个问题。这篇的写法都是「先窄后宽」。

一、先确认在哪抓

ip -br addr          # 看有哪些接口、各自的地址
ip route get 1.1.1.1 # 看访问外网走哪个接口
  • 抓本机进程之间的通信,用 -i lo。它在 any 上常常看不到,这是最容易卡住的一步。
  • 抓对外流量,用具体网卡名(eth0、ens3)比 any 准确,也不会抓到无关流量。
  • -i any 方便,但链路层头会显示成 Linux cooked,做协议分析时不如指定网卡。

二、权限:为什么普通用户报「Operation not permitted」

抓包需要 CAP_NET_RAW 能力,普通用户默认没有。三种做法:

# 1) 直接 sudo(最省事)
sudo tcpdump -i eth0

# 2) 给二进制加能力(注意:这等于放开了抓包权限,谨慎)
sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/tcpdump

# 3) 抓成文件,改属主后用自己的账号离线分析(推荐)
sudo tcpdump -i eth0 -w /tmp/x.pcap
sudo chown $USER /tmp/x.pcap

第 3 种最稳:线上机器上不放开权限,抓完再回本地用 Wireshark 慢慢看。

三、过滤器:BPF 语法的基础

tcpdump 的过滤表达式就是 BPF,常用的是这几个维度:

-nn                      # 不做 DNS 反解、端口显示成数字(少了等待,速度明显快)
host 10.0.0.12           # 某个 IP 的收发
src host 10.0.0.12       # 只看来向
dst port 443             # 目标是 443
port 8080                # 源或目标是 8080
net 10.0.0.0/24          # 整段
tcp and not port 22      # 组合,排除自己的 SSH 会话

几个真正常用的组合:

# 只看 TCP 建连(SYN 置位且 ACK 未置位)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

# 看有没有被 RST(对端拒绝或端口未开)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'

# 只看某台后端、并且排除 SSH
sudo tcpdump -i eth0 -nn 'host 10.0.0.12 and tcp and not port 22'

四、输出怎么读

14:32:07.918273 IP 10.0.0.5.51234 > 10.0.0.12.80: Flags [S], seq 1234567, win 64240, length 0
  • Flags [S] 发起连接,[S.] 回应,[.] 是普通 ACK,[P.] 带数据,[F.] 关闭,[R] 重置。
  • seq 是序列号,length 0 表示这个包不带负载。
  • 只看到 [S] 没有 [S.],说明对端没回——要么没收到,要么被防火墙丢了。
  • 看到 [R] 立刻回,通常是端口没在监听。

五、看内容:-A 和 -X

sudo tcpdump -i eth0 -nn -A -s0 'tcp port 80'   # 按 ASCII 打印负载
sudo tcpdump -i eth0 -nn -X -s0 'tcp port 80'   # 十六进制 + ASCII 并排

-s0 表示抓整包(不截断)。不带它的话会有一个默认截断长度, 抓 HTTP 头够用,抓带 body 的请求就会被切掉。

明文协议(HTTP、Redis、MySQL 的旧协议)能这么看; HTTPS 只能看到 TLS 记录层的长度和类型,看不到内容——这是设计如此,不是抓包工具的问题。

六、边抓边注意磁盘

# 循环写文件,每 100MB 一个,最多留 10 个(够回看最近一段)
sudo tcpdump -i eth0 -nn -s0 -w /tmp/cap.pcap -C 100 -W 10 'tcp port 8080'

千兆链路上跑满时,pcap 每分钟能长到几百 MB。不带 -C/-W 就在生产机上一直抓,把磁盘写满只是时间问题。

七、离线分析

tcpdump -nn -r /tmp/cap.pcap 'tcp port 8080' | head -50
tcpdump -nn -tttt -r /tmp/cap.pcap        # -tttt 显示完整日期时间

更复杂的需求就拉到本地用 Wireshark 看:Follow TCP Stream 能拼出完整会话, 统计里的「专家信息」会直接标出重传、乱序、零窗口这些异常。

先分清是「包没到」还是「到了但慢」:抓在服务端网卡上能看到 SYN 却看不到后续数据, 问题在对端或中间链路;两个方向都有包但间隔很大,才是服务端自己的处理慢。


一句话总结:先用最窄的过滤器抓一小段,存成 pcap 再慢慢看;抓不到包先确认接口和权限,别急着怀疑网络。