概述

凌晨两点,你被电话吵醒。订单系统大面积超时,但 CPU 正常、内存正常、磁盘 IO 正常。重启服务没用,回滚也没用。你盯着监控大盘,一切指标都是绿的,唯独用户在骂。

十有八九,是网络层面的问题。这时候你需要的是一双能看见数据包的眼睛。

tcpdump 就是这双眼睛。它不是什么新工具——1990 年代就有了——但到今天仍然是 Linux 上最硬核的网络诊断手段。说直白点:如果你只会看监控图表、不会抓包,那遇到网络层问题时你就是个瞎子。

这篇文章不讲花哨的概念,就讲实战:tcpdump 怎么抓、BPF 过滤器怎么写、pcap 文件怎么用 Wireshark 分析、TCP 三次握手和 TLS 握手在抓包里长什么样、以及那些我踩过坑才学会的技巧。

tcpdump 基础:先搞懂你在抓什么

什么是抓包

网卡收到的每一个数据帧,正常情况下只有操作系统内核会处理,用户态程序看不到原始内容。抓包就是把网卡的混杂模式(promiscuous mode)打开,让内核把所有流经网卡的数据包副本都交给抓包工具。

打个比方:正常情况下网卡像个只读收件箱的快递员,只把发给你的包裹送上门。开了混杂模式后,它变成监控摄像头,把整条街上经过的所有包裹都拍下来——不管是不是给你的。

tcpdump vs Wireshark:分工不同

对比维度tcpdumpWireshark
运行环境服务器命令行,SSH 即可需要图形界面
资源占用极低(几 MB 内存)较高(GUI 程序)
核心能力捕获+保存 pcap深度协议解析+交互式分析
过滤语法BPF(Berkeley Packet Filter)显示过滤器(Display Filter)
适用场景生产服务器实时抓包、长期后台捕获本地分析 pcap 文件、协议细节排查
自动化可写成脚本、对接告警不适合自动化

实际工作中的标准流程:服务器上用 tcpdump 抓包保存成 pcap 文件,scp 下载到本地,用 Wireshark 打开分析。这个组合我在过去七年里用了不下五百次。

安装与权限

大多数 Linux 发行版预装了 tcpdump。检查一下:

which tcpdump || echo "未安装"
tcpdump --version

没装的话:

# Debian/Ubuntu
sudo apt-get install -y tcpdump

# CentOS/RHEL
sudo yum install -y tcpdump

权限管理是个坑。tcpdump 需要 CAP_NET_RAW 能力才能抓包,默认只有 root 能用。但生产环境你不可能给每个人都 root 权限。推荐做法是配置 sudo 白名单:

# 创建专用 sudoers 配置
sudo visudo -f /etc/sudoers.d/tcpdump

# 内容:允许 ops 组的成员免密运行 tcpdump
%ops ALL=(root) NOPASSWD: /usr/sbin/tcpdump

这样运维人员用 sudo tcpdump 就能抓包,不需要完整 root 权限。别图省事直接 chmod +s /usr/sbin/tcpdump——那是给所有用户开了 root 后门。

核心参数速查

先列一张表,后面逐个展开。

参数全称作用示例
-iinterface指定网卡tcpdump -i eth0
-nnumeric不解析主机名tcpdump -n
-nn不解析主机名和端口名tcpdump -nn
-vverbose详细输出(可叠加 -vv -vvv)tcpdump -vvv
-ccount抓 N 个包后停止tcpdump -c 100
-wwrite保存为 pcap 文件tcpdump -w out.pcap
-rread读取 pcap 文件tcpdump -r out.pcap
-ssnaplen截断长度(默认 262144)tcpdump -s 0(不截断)
-AASCII以 ASCII 显示包内容tcpdump -A
-Xhex+ASCII十六进制+ASCII 显示tcpdump -X
-Grotate按时间轮转文件tcpdump -G 60 -w out_%Y%m%d_%H%M%S.pcap
-Wcount轮转文件数量上限tcpdump -W 10 -G 60 -w out.pcap
-Dlist列出可用网卡tcpdump -D

常用参数组合

# 最常用的生产抓包命令
sudo tcpdump -i eth0 -nn -s 0 -w capture.pcap

# 实时看 HTTP 流量(仅文本协议适用)
sudo tcpdump -i eth0 -nn -A -s 0 'tcp port 80'

# 抓 1000 个包就停
sudo tcpdump -i eth0 -nn -c 1000 -w capture.pcap

# 按小时轮转,最多保留 24 个文件
sudo tcpdump -i eth0 -nn -s 0 -G 3600 -W 24 -w /var/log/tcpdump/capture_%Y%m%d_%H.pcap

-n-nn 为什么重要

不加 -n,tcpdump 会尝试把 IP 地址反解成主机名。在生产环境中,这意味着每抓一个包都要发一个 DNS 查询。如果你正在排查的就是 DNS 问题——恭喜,你的抓包工具本身制造了 DNS 风暴。

-nn 更彻底:连端口号都不解析。不加的话 tcpdump 会把 443 显示成 https,看起来方便,但在写过滤规则时容易混淆。-nn 强制全数字输出,干净利落。

BPF 过滤器:精准捕获的艺术

BPF(Berkeley Packet Filter)是 tcpdump 的过滤引擎。它在内核态运行,不符合规则的数据包直接被丢弃,不会拷贝到用户态。这意味着 BPF 过滤的性能极高——你可以用 BPF 在万兆网卡上实时过滤而不丢包。

过滤语法基础

BPF 过滤表达式由三部分组成:

类型   方向   协议   值
host   src    tcp    192.168.1.100
组成部分可选值说明
类型hostnetportportrange指定按什么维度过滤
方向srcdstsrc or dst(默认)指定源或目的
协议tcpudpicmparpipip6ether限定协议
逻辑andornot组合条件

常用过滤示例

# 抓特定主机的所有流量
sudo tcpdump -i eth0 -nn host 10.0.0.5

# 抓源 IP 为 10.0.0.5 的流量
sudo tcpdump -i eth0 -nn src host 10.0.0.5

# 抓目的端口为 443 的 TCP 流量
sudo tcpdump -i eth0 -nn 'tcp dst port 443'

# 抓两个主机之间的通信
sudo tcpdump -i eth0 -nn 'host 10.0.0.5 and host 10.0.0.6'

# 抓 DNS 查询(UDP 53)
sudo tcpdump -i eth0 -nn 'udp port 53'

# 抓 ICMP(ping)
sudo tcpdump -i eth0 -nn icmp

# 排除 SSH 自身的流量(避免抓包产生循环)
sudo tcpdump -i eth0 -nn 'not port 22'

# 抓特定网段
sudo tcpdump -i eth0 -nn 'net 10.0.0.0/24'

# 组合过滤:10.0.0.5 到 10.0.0.6 的 443 端口流量
sudo tcpdump -i eth0 -nn 'host 10.0.0.5 and host 10.0.0.6 and tcp port 443'

TCP 标志位过滤

这是排查连接问题的关键。TCP 报文头中有 6 个标志位,BPF 可以精确过滤:

标志位BPF 写法含义
SYNtcp[tcpflags] & tcp-syn != 0连接请求
ACKtcp[tcpflags] & tcp-ack != 0确认
FINtcp[tcpflags] & tcp-fin != 0关闭连接
RSTtcp[tcpflags] & tcp-rst != 0重置连接
PSHtcp[tcpflags] & tcp-push != 0推送数据
URGtcp[tcpflags] & tcp-urg != 0紧急数据
# 只抓 SYN 包(看谁在发起连接)
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'

# 只抓 FIN 包(谁在关闭连接)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-fin != 0'

实测发现,SYN 过滤在排查连接超时问题时极为高效。有一次我遇到一个微服务偶发超时,监控看不出异常。用 SYN 过滤抓了五分钟,发现客户端在 SYN 发出后等了 3 秒没收到 SYN-ACK,然后重试——服务端确实没回。进一步排查发现是服务端 conntrack 表满了。

抓包大小过滤

# 抓大于 1400 字节的包(排查大包分片问题)
sudo tcpdump -i eth0 -nn 'greater 1400'

# 抓小于 60 字节的包(可能是异常的 ACK 包)
sudo tcpdump -i eth0 -nn 'less 60'

过滤器的常见陷阱

陷阱一:括号没引号包裹

# 错误写法——shell 会吃掉括号
sudo tcpdump -i eth0 host 10.0.0.5 and (port 80 or port 443)

# 正确写法——用引号包裹
sudo tcpdump -i eth0 'host 10.0.0.5 and (port 80 or port 443)'

陷阱二:方向写反

src host 10.0.0.5 是源 IP 是 10.0.0.5,dst host 10.0.0.5 是目的 IP 是 10.0.0.5。写反了就是抓错方向,对着空气分析半天。

陷阱三:忘了排除 SSH 流量

SSH 到服务器上跑 tcpdump,tcpdump 本身的输出也会经过 SSH 通道。如果不排除 22 端口,你会抓到自己的 SSH 流量,在终端上形成正反馈循环,刷屏到死。

# 保险写法
sudo tcpdump -i eth0 -nn 'not port 22 and not port 53' -w capture.pcap

抓包策略:生产环境不能瞎抓

磁盘和性能考量

在万兆网卡上全量抓包,一分钟就能产生几个 GB 的数据。如果不加过滤直接抓,磁盘很快就会被撑满。这不是理论——我见过有人 tcpdump -i eth0 -w capture.pcap 挂了一晚上,第二天早上发现 / 分区 100%,业务全部挂了。

生产抓包铁律

  1. 永远加过滤条件,哪怕只是排除 SSH 流量
  2. -c 限制包数量,或者用 -G + -W 做轮转
  3. 写到专用目录,别写 /tmp——容器环境 /tmp 可能是 tmpfs,吃内存
  4. 监控磁盘剩余空间,写个简单脚本兜底
# 安全的生产抓包方案
sudo mkdir -p /var/log/tcpdump
sudo tcpdump -i eth0 -nn -s 0 \
  -G 300 -W 48 \
  -w /var/log/tcpdump/capture_%Y%m%d_%H%M%S.pcap \
  'host 10.0.0.5 and tcp port 443'

# -G 300:每 5 分钟轮转一个文件
# -W 48:最多保留 48 个文件(4 小时)
# 过滤特定主机和端口,不会抓到无关流量

snaplen 的坑

-s 参数控制每个包截取多少字节。默认值在不同版本不同:

  • 老版本默认 68 或 96 字节——只能看到头部
  • 新版本默认 262144 字节——基本是全包

如果你用老版本 tcpdump 抓 TLS 握手,证书包经常超过 1500 字节,snaplen 设小了就截断了 ServerHello 里的证书链。排查 TLS 问题时一定加 -s 0

# -s 0 表示不截断,抓完整包
sudo tcpdump -i eth0 -nn -s 0 -w tls_capture.pcap 'tcp port 443'

Wireshark 分析:从 pcap 到根因

tcpdump + Wireshark 协同工作流

# 步骤1:服务器上抓包
sudo tcpdump -i eth0 -nn -s 0 -w /tmp/capture.pcap 'host 10.0.0.5 and tcp port 443'

# 步骤2:下载到本地
scp user@server:/tmp/capture.pcap ./

# 步骤3:本地用 Wireshark 打开
wireshark capture.pcap &

如果你不想每次都 scp,可以用 SSH 管道实时传输:

# 远程抓包,本地直接用 Wireshark 打开
ssh user@server 'sudo tcpdump -i eth0 -nn -s 0 -w - "host 10.0.0.5"' | wireshark -k -i -

这条命令在 macOS 和 Linux 上都能用。-w - 让 tcpdump 把 pcap 数据写到 stdout,管道传给 Wireshark 的 stdin,-k -i - 让 Wireshark 从 stdin 读取并立即开始。实测延迟在 1-2 秒左右,排查实时问题非常顺手。

Wireshark 显示过滤器

注意:Wireshark 的显示过滤器和 tcpdump 的 BPF 过滤器语法完全不同。这是新手最常见的困惑。

对比BPF(tcpdump)Display Filter(Wireshark)
IP 地址host 10.0.0.5ip.addr == 10.0.0.5
端口port 443tcp.port == 443
TCP SYNtcp[tcpflags] & tcp-syn != 0tcp.flags.syn == 1
TCP RSTtcp[tcpflags] & tcp-rst != 0tcp.flags.reset == 1
协议tcptcp
组合and / or / notand / or / not(同)

常用的 Wireshark 显示过滤器:

# 只看 HTTP 请求
http.request

# 只看 TLS 握手
tls.handshake

# 只看 TCP 重传
tcp.analysis.retransmission

# 只看 TCP 重复 ACK
tcp.analysis.duplicate_ack

# 查看特定 HTTP 路径
http.request.uri contains "api/order"

# 查看特定 TCP 流
tcp.stream eq 42

# 查看连接重置
tcp.flags.reset == 1

右键追踪 TCP 流

这是 Wireshark 最常用的功能。在一个 TCP 数据包上右键 → Follow → TCP Stream,Wireshark 会把这条 TCP 连接的所有数据包按时间顺序拼成一段对话,左边是客户端发的,右边是服务端发的。

对于 HTTP 等明文协议,这个功能让你能像读聊天记录一样看到完整的请求-响应过程。但 TLS 流量是加密的,追踪 TCP 流只能看到加密后的数据。

协议解析实战

TCP 三次握手在抓包里长什么样

一个正常的 TCP 连接建立过程,抓包看是这样的:

10:30:01.123456 IP 10.0.0.5.54321 > 10.0.0.6.443: Flags [S], seq 1234567890, win 64240, [mss 1460,sackOK,TS val 1234567890 ecr 0,nop,wscale 7], length 0
10:30:01.123567 IP 10.0.0.6.443 > 10.0.0.5.54321: Flags [S.], seq 9876543210, ack 1234567891, win 65160, [mss 1460,sackOK,TS val 9876543210 ecr 1234567890,nop,wscale 7], length 0
10:30:01.123578 IP 10.0.0.5.54321 > 10.0.0.6.443: Flags [.], ack 9876543211, win 502, length 0

解读:

步骤标志含义
第1包[S] (SYN)客户端:“我想连你,我的序号是 1234567890”
第2包[S.] (SYN+ACK)服务端:“收到,我同意,我的序号是 9876543210,确认你的 1234567891”
第3包[.] (ACK)客户端:“收到你的确认,连接建立”

标志位速查:

  • [S] = SYN
  • [.] = ACK
  • [S.] = SYN + ACK
  • [P.] = PSH + ACK(有数据要传)
  • [F.] = FIN + ACK(我要关了)
  • [R.] = RST + ACK(连接异常,重置)
  • [R] = RST(直接重置,不含 ACK)

排查 TCP 连接超时

如果服务超时但不知道是哪一层的问题,先抓 SYN 包:

sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0' -c 100

正常情况下,每个 SYN 后面应该紧跟一个 SYN-ACK。如果只看到 SYN 没有 SYN-ACK,说明:

现象可能原因下一步
SYN 发出,无任何回应防火墙丢弃、路由不通、服务未启动检查 iptables 规则、路由表、服务状态
SYN 发出,收到 RST服务未监听该端口、被 TCP wrapper 拒绝检查 ss -tlnp 确认端口监听状态
SYN 发出,SYN-ACK 返回但后续无 ACK客户端问题,可能 NAT 超时或路由不对称在客户端抓包对比
大量 SYN 无 SYN-ACK服务端 SYN backlog 满了(SYN flood 攻击或突发连接)检查 netstat -s | grep SYNs

排查 TLS 握手失败

TLS 握手比 TCP 复杂得多。一次完整的 TLS 1.2 握手需要 2 个 RTT:

# 抓 TLS 握手流量
sudo tcpdump -i eth0 -nn -s 0 -w tls.pcap 'tcp port 443'

用 Wireshark 打开后,过滤 tls.handshake,你会看到:

步骤消息方向内容
1ClientHello客户端→服务端支持的密码套件、TLS 版本、SNI(域名)
2ServerHello服务端→客户端选定的密码套件、TLS 版本
3Certificate服务端→客户端服务器证书链
4ServerKeyExchange服务端→客户端DH 参数(如使用 ECDHE)
5ServerHelloDone服务端→客户端“我的消息发完了”
6ClientKeyExchange客户端→服务端客户端的 DH 参数
7ChangeCipherSpec客户端→服务端“后续消息开始加密”
8Finished客户端→服务端加密的握手完成验证
9ChangeCipherSpec服务端→客户端“我也要开始加密了”
10Finished服务端→客户端加密的握手完成验证

常见 TLS 问题排查:

场景一:证书过期

在 Wireshark 中过滤 tls.handshake.type == 11(Certificate),展开证书详情,检查 validity.not_after 字段。如果发现证书已过期,就是这个问题。

tcpdump 命令行也能看:

# 用 tshark 解析 TLS 证书
tshark -r tls.pcap -Y "tls.handshake.type == 11" -T fields -e tls.handshake.certificate

场景二:SNI 不匹配

SNI(Server Name Indication)是客户端在 ClientHello 中携带的目标域名。如果服务端配置了多个虚拟主机但 SNI 没配对,可能返回错误的证书。过滤 tls.handshake.type == 1(ClientHello)查看 SNI 字段:

tshark -r tls.pcap -Y "tls.handshake.type == 1" -T fields -e tls.handshake.extensions_server_name

场景三:密码套件协商失败

如果 ClientHello 发出后直接收到 Alert 消息,说明密码套件没谈拢。检查 ClientHello 中的 Cipher Suites 列表和服务端支持的列表是否交集为空。

HTTP 流量分析

虽然现在大部分流量都走 HTTPS 了,但内部服务间的 HTTP 通信仍然常见。用 -A 参数可以直接看到 HTTP 内容:

sudo tcpdump -i eth0 -nn -A -s 0 'tcp port 80 and host 10.0.0.5'

输出中你会看到类似这样的内容:

GET /api/v1/orders?status=pending HTTP/1.1
Host: order-service.internal
User-Agent: curl/7.81.0
Accept: */*
Connection: keep-alive

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 142

{"orders": [...]}

但别在生产环境长期开 -A 输出到终端——不仅性能差,还可能把敏感信息(token、密码)暴露在终端日志里。

DNS 问题排查

DNS 是网络问题的高发区。一条 DNS 查询的抓包很简单:

sudo tcpdump -i eth0 -nn -l 'udp port 53' | grep -E 'A\?|AAAA\?'

-l 是行缓冲模式,让输出实时刷新。A? 表示 A 记录查询,AAAA? 表示 IPv6 查询。

# 抓 DNS 查询和响应
sudo tcpdump -i eth0 -nn 'udp port 53' -c 20

输出示例:

12:30:01.123 IP 10.0.0.5.43210 > 8.8.8.8.53: 45231+ A? api.example.com. (33)
12:30:01.156 IP 8.8.8.8.53 > 10.0.0.5.43210: 45231 2/0/0 A 93.184.216.34, A 93.184.216.35 (69)
  • 45231+ 中的 + 表示递归查询
  • 2/0/0 表示 2 个回答记录、0 个权威记录、0 个附加记录
  • 如果看到响应是 0/0/00/1/0(NXDOMAIN),说明域名不存在

实战案例

案例一:服务间调用偶发 502

现象:A 服务调 B 服务的 HTTP 接口,偶发 502 Bad Gateway,频率约千分之一。

排查过程

# 在 B 服务所在机器抓包
sudo tcpdump -i eth0 -nn -s 0 -w 502.pcap 'host <A的IP> and tcp port 8080'

等复现后用 Wireshark 打开,过滤 tcp.analysis.retransmission or tcp.analysis.duplicate_ack or tcp.flags.reset == 1,发现:

  1. TCP 三次握手正常
  2. 客户端发送 HTTP 请求后,服务端 ACK 了但没返回数据
  3. 客户端等待 15 秒后发送 FIN 关闭连接
  4. Nginx(反向代理)在 B 服务超时后返回 502

根因:B 服务的连接池配置太小,高峰期连接被排队等待,超过 Nginx 的 proxy_read_timeout。不需要改网络,调大连接池即可。

案例二:跨机房延迟突增

现象:北京机房到上海机房的 RPC 调用,平时 30ms,突然变成 200ms+。

# 双向抓包
sudo tcpdump -i eth0 -nn -s 0 -w latency.pcap 'host <上海机房IP>'

Wireshark 打开后用 tcp.analysis.ack_rtt 过滤器查看 RTT 分布。发现部分包的 ACK RTT 超过 200ms,且这些包的 TTL 值比正常包多了 3 跳。

根因:动态路由策略变更,部分流量绕行了额外 3 跳,导致延迟增加。联系网络组修正路由策略后恢复。

案例三:ARP 欺骗导致间歇性断网

现象:某台服务器间歇性无法访问网关,每次持续 10-30 秒自动恢复。

# 抓 ARP 包
sudo tcpdump -i eth0 -nn arp

正常情况下,ARP 缓存有效期内不会频繁发 ARP 请求。但抓包发现:

14:20:01 IP (via eth0) arp who-has 10.0.0.1 tell 10.0.0.5
14:20:01 IP (via eth0) arp reply 10.0.0.1 is-at 00:11:22:33:44:55  ← 正常网关MAC
14:20:03 IP (via eth0) arp reply 10.0.0.1 is-at 66:77:88:99:aa:bb  ← 异常MAC!

根因:另一台机器配置了错误 IP,ARP 响应抢先覆盖了正确网关的 MAC 地址,导致流量发往错误机器。修正那台机器的 IP 配置后恢复正常。

tshark:命令行版的 Wireshark

不是所有场景都能用 GUI。tshark 是 Wireshark 的命令行版本,支持完整的协议解析能力,适合在服务器上直接分析 pcap 文件。

# 安装
sudo apt-get install -y tshark   # Debian/Ubuntu
sudo yum install -y wireshark     # CentOS/RHEL(包含 tshark)

# 统计 pcap 中的协议分布
tshark -r capture.pcap -q -z io,phs

# 提取所有 HTTP 请求的 URL
tshark -r capture.pcap -Y "http.request" -T fields -e http.host -e http.request.uri

# 统计 TCP 重传
tshark -r capture.pcap -Y "tcp.analysis.retransmission" | wc -l

# 查看 TLS SNI
tshark -r capture.pcap -Y "tls.handshake.type == 1" -T fields -e tls.handshake.extensions_server_name

# 统计各 IP 的包数量(Top 10)
tshark -r capture.pcap -q -z conv,ip | sort -t'|' -k1 -rn | head -10

高级技巧

用 ngrep 抓特定内容

如果你只想看包含特定字符串的流量,ngrep 比 tcpdump 方便:

# 安装
sudo apt-get install -y ngrep

# 抓包含 "error" 的 HTTP 流量
sudo ngrep -d eth0 -W byline 'error' 'tcp port 80'

# 抓包含特定 token 的请求
sudo ngrep -d eth0 -W byline 'Authorization: Bearer eyJ...' 'tcp port 443'

但注意,ngrep 只对明文协议有效。HTTPS 流量加密了,ngrep 看不到内容。

用 ss + tcpdump 联合诊断

先看当前连接状态,再针对性抓包:

# 查看与 10.0.0.6 的所有连接
ss -tn state established '( dst 10.0.0.6 )'

# 查看 TIME-WAIT 状态的连接数量
ss -tn state time-wait | wc -l

# 查看 SYN-RECV 状态的连接(可能遭受 SYN flood)
ss -tn state syn-recv | wc -l

如果发现大量 SYN-RECV 状态的连接,说明服务端收到了 SYN 但没收到第三个 ACK。可能是攻击,也可能是中间网络丢包。

抓包性能基准

在万兆网卡上抓包,性能取决于 BPF 过滤的复杂度和 snaplen:

# 用 dropwatch 看 BPF 过滤丢包情况
sudo dropwatch -l kas

# 如果看到大量 "kfree_skb" 在 __netif_receive_skb_core,
# 说明内核在 BPF 过滤前就丢包了,需要降低抓包量

如果确实需要全量抓包但性能跟不上,考虑用 PF_RING 或 AF_PACKET 的 mmap 模式。这些技术可以绕过内核拷贝,直接从网卡 DMA 到用户态内存。Facebook 的 fbtaxii 体系和 Netflix 的内部工具都用了类似技术。

生产环境注意事项

  1. 别抓全量流量。万兆网卡全量抓包几分钟就几十 GB,而且生产环境的流量里可能有敏感信息(API token、用户数据)。精确过滤是你的第一道安全措施。

  2. pcap 文件含敏感信息。pcap 文件包含完整的网络数据,HTTPS 之外的所有内容都是明文。别把 pcap 文件放在公开可访问的地方,别通过不安全的渠道传输。用完就删。

  3. 长时间抓包要轮转。用 -G + -W 组合做时间轮转和数量限制,防止磁盘被撑满。

  4. 容器环境中抓宿主机流量。在容器里抓包只能看到容器命名空间内的流量。要抓宿主机流量,需要用 hostNetwork: true 或者直接在宿主机上运行 tcpdump。

# 在 K8s Pod 中抓包(需要 hostNetwork 或特权模式)
kubectl exec -it <pod> -- tcpdump -i eth0 -nn -c 100

# 在宿主机上抓 Pod 流量
# 先找到 Pod 的 veth pair
kubectl get pod <pod> -o jsonpath='{.status.podIP}'
# 然后在宿主机上抓这个 IP 的流量
sudo tcpdump -i eth0 -nn 'host <pod-IP>'
  1. 时区问题。tcpdump 输出的时间戳默认是本地时间。如果服务器和你的时区不同,时间戳会差几个小时。用 -tttt 可以显示日期:
# 显示完整日期时间
sudo tcpdump -i eth0 -nn -tttt

# 输出:2026-07-14 10:30:01.123456 IP ...

总结

tcpdump 和 Wireshark 是 SRE 排查网络问题的核心工具组合。tcpdump 负责在生产服务器上高效捕获,Wireshark 负责在本地深度解析。两者配合的流程很简单:服务器抓包 → scp 下载 → Wireshark 分析。

核心经验:

  • BPF 过滤器是你的第一道防线,不仅能减少无关流量,还能防止磁盘被撑满。写过滤表达式时用引号包裹括号。
  • TCP 标志位过滤是排查连接问题的关键。SYN 过滤看谁在发连接、RST 过滤看谁在拒绝连接、FIN 过滤看谁在关连接。
  • -nn 是生产标配,避免 DNS 反解产生的性能损耗和干扰。
  • -s 0 确保 TLS 握手包不被截断,大证书链经常超过 1500 字节。
  • pcap 文件包含敏感信息,HTTPS 之外全是明文,用完即删。
  • tshark 在无 GUI 环境下替代 Wireshark,支持完整的协议解析和字段提取。
  • 长时间抓包必须用 -G + -W 轮转,否则你会在某天凌晨被告警吵醒——不是因为业务故障,而是因为磁盘满了。

抓包能力的提升没有捷径,就是多练。下次遇到网络问题,别急着重启服务,先抓个包看看——十次有八次,答案就在 pcap 里。

参考资料与致谢

本文在撰写过程中参考了以下资料,感谢原作者的贡献:

  1. tcpdump 官方手册 — tcpdump.org,BPF 过滤语法和命令参数的权威文档
  2. Wireshark 用户指南 — Wireshark.org,显示过滤器和协议解析的完整文档
  3. tcpdump 抓包实战技巧 — CSDN,生产环境 tcpdump 使用经验和排查案例
  4. 网络分析双雄:Tcpdump 结合 Wireshark 协议分析实战指南 — CSDN,tcpdump 与 Wireshark 协同工作流的实践总结
  5. 网络安全分析:tcpdump 命令精准筛选 pcap 包 — CSDN,BPF 高级过滤技巧和 pcap 文件分析