网络技术

网络抓包分析实战:tcpdump、Wireshark 与 tshark 的排查三剑客

✎ -- 字 🕐 -- 分钟
字号

网络抓包分析实战:tcpdump、Wireshark 与 tshark 的排查三剑客

一、为什么网络抓包是必备技能

当你遇到"请求超时但 ping 通""API 偶发 502""数据库连接偶尔断开"这类问题时,日志往往只能告诉你结果,却看不到过程。网络抓包就像给网络流量装了一个黑匣子,让你看到每一帧数据包的完整生命周期。

我从 2018 年开始系统性使用抓包工具排查问题,累计处理过几百个网络相关故障。这篇总结是我筛选出来的最高频、最实用的抓包方法论,覆盖了从线上应急到事后复盘的全场景。

二、tcpdump:线上排障的第一选择

2.1 基础语法与核心参数

tcpdump 的优势在于:服务器上几乎都有、无需图形界面、性能开销极低。线上出问题第一时间抓包,tcpdump 是不二之选。

# 基础抓包:监听 eth0 接口,显示详细信息
sudo tcpdump -i eth0 -nn -v

# 只抓 80 端口,保存到文件(线上排障标准姿势)
sudo tcpdump -i any port 80 -w /tmp/capture.pcap -nn

# 限制抓包数量,避免磁盘写满
sudo tcpdump -i eth0 -c 1000 -w /tmp/capture.pcap

# 抓取特定主机的通信
sudo tcpdump host 192.168.1.100 -w /tmp/host.pcap

# 只抓 TCP SYN 包(快速发现扫描行为)
sudo tcpdump "tcp[tcpflags] & tcp-syn != 0" -nn

常用参数解释:

参数含义使用场景
-i指定网卡接口多网卡服务器必选
-nn不解析域名和端口名加速显示,避免 DNS 查询
-v / -vv / -vvv详细程度递增需要看完整协议头时加
-w写入 pcap 文件保存后离线分析
-c限制抓包数量防止磁盘爆炸
-s 0抓完整数据包默认 68 字节可能截断

2.2 BPF 过滤表达式实战

Berkeley Packet Filter 是 tcpdump 的灵魂。掌握它,你可以在千万级数据包中秒级定位目标。

# 组合过滤:来自 10.0.0.0/8 网段、访问 443 端口的 TCP 流量
sudo tcpdump -i eth0 'src net 10.0.0.0/8 and dst port 443 and tcp'

# 排除特定端口,只看业务流量
sudo tcpdump -i eth0 'not port 22 and not port 53'

# 抓取 HTTP POST 请求(TCP 负载前 4 字节为 POST)
sudo tcpdump -i eth0 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354' -A -s 0

# 检测 TCP 重传(快速发现网络质量或服务端问题)
sudo tcpdump -i eth0 'tcp[13] & 8 != 0' -nn  # PSH 标志,常用于重传场景

一个真实的排查案例:某服务偶发 500ms 延迟,怀疑是 Nginx 到后端连接池问题。我用以下命令实时抓取了 Nginx 与 upstream 的交互:

sudo tcpdump -i lo port 8080 -w /tmp/nginx_upstream.pcap -nn -s 0

Wireshark 打开后发现:大量 TCP 连接处于 TIME_WAIT 状态,新请求被迫等待端口复用。调整 net.ipv4.tcp_tw_reuse 后问题解决。没有抓包,这类问题靠猜几乎不可能定位。

2.3 高级用法:分段与性能

# 轮询保存,每 100MB 自动切新文件,保留最近 10 个文件
sudo tcpdump -i eth0 -w /tmp/capture.pcap -C 100 -W 10 -nn -s 0

# 抓包时同时显示摘要(适合边抓边看)
sudo tcpdump -i eth0 -w /tmp/capture.pcap -nn -s 0 -v

# 基于文件大小 + 时间双重限制(守护进程模式)
sudo tcpdump -i eth0 -w /tmp/capture.pcap -G 3600 -C 500 -nn -s 0

三、Wireshark:图形化深度分析

3.1 从 pcap 到结论的标准流程

tcpdump 抓完的数据包,上传到本地用 Wireshark 分析。我的标准分析流程是:

  1. Statistics → Protocol Hierarchy:先看流量分布,确认协议占比是否符合预期
  2. Telephony → Flow Graph:看 TCP 流的时间轴,一眼定位重传、乱序
  3. Expert Info(左下角):Wireshark 自动标记的异常,包括重传、乱序、窗口满等
  4. Apply Display Filter:精确定位到特定会话或异常包

3.2 核心过滤语法(Display Filter)

Wireshark 的 Display Filter 和 tcpdump 的 BPF 语法完全不同,容易混淆。以下是我最高频使用的过滤器:

# 按 IP 和端口过滤
tcp.port == 443
ip.addr == 192.168.1.100
ipv6.addr == ::1

# 按 TCP 标志过滤
tcp.flags.syn == 1 && tcp.flags.ack == 0    # 只看 SYN 包(发现扫描)
tcp.analysis.retransmission                  # 只看重传包
tcp.analysis.duplicate_ack                   # 只看重复 ACK

# 按 HTTP 内容过滤
http.request.method == "POST"
http.response.code == 502
http.host contains "api.example.com"

# 按 TLS/SSL 过滤
ssl.handshake.type == 1                      # Client Hello
tls.handshake.type == 11                     # Certificate 报文

# 按数据包长度过滤(快速发现大报文或空包)
frame.len > 1000
udp.length == 0

3.3 分析 TCP 性能问题的利器

Wireshark 内置的 TCP Stream Graphs 是排查性能问题的神兵利器。打开方式:选中任意 TCP 包 → Statistics → TCP Stream Graphs。

图表类型排查目标异常特征
Time-Sequence Graph (Stevens)TCP 发送窗口与重传平台期表示窗口耗尽,断崖表示重传
Round Trip Time Graph网络延迟稳定性RTT 突增表示网络抖动或路由变化
Throughput Graph实际传输带宽远低于带宽表示存在瓶颈
Window Scaling Graph接收窗口大小变化窗口持续为 0 表示接收方处理不过来

经典场景:客户端下载速度慢,iperf 测试带宽正常。抓包后打开 Throughput Graph,发现实际传输速率只有 10Mbps。再看 Time-Sequence Graph,大量锯齿状重传。最终定位是路由器 QoS 规则误生效,导致随机丢包。

3.4 解密 HTTPS 流量(本地调试)

Wireshark 支持解密 SSL/TLS,前提是有私钥或浏览器会话密钥。本地调试时,导出 Chrome 的会话密钥即可解密:

# 1. 设置环境变量导出密钥(Linux/macOS)
export SSLKEYLOGFILE=/tmp/ssl-keys.log

# 2. 用该环境变量启动 Chrome
google-chrome --ssl-key-log-file=/tmp/ssl-keys.log

# 3. Wireshark 设置 → Protocols → TLS → (Pre)-Master-Secret log filename
# 填入 /tmp/ssl-keys.log,即可解密所有 TLS 流量

注意:这个能力仅用于本地调试,线上环境私钥不可泄露。但它对分析 HTTPS 下的 API 问题极其有效。

四、tshark:自动化与批量处理的终极方案

4.1 为什么需要 tshark

Wireshark 的 GUI 功能强大,但无法批量处理。当你有 100 个 pcap 文件要提取统计信息,或需要在 CI/CD 中自动化网络验证时,tshark 是唯一的答案。

4.2 核心命令模板

# 读取 pcap 并输出 JSON 格式(方便后续脚本处理)
tshark -r capture.pcap -T json -e ip.src -e ip.dst -e tcp.port -e http.host

# 提取所有 HTTP 请求路径和响应码
tshark -r capture.pcap -Y "http.request or http.response" \
  -T fields -e http.request.uri -e http.response.code

# 统计 Top 10 请求来源 IP
tshark -r capture.pcap -T fields -e ip.src | sort | uniq -c | sort -rn | head -10

# 提取所有 DNS 查询和响应
tshark -r capture.pcap -Y "dns" -T fields \
  -e dns.qry.name -e dns.resp.addr -E header=y -E separator=,

# 检测 TCP 重传数量(快速评估网络质量)
tshark -r capture.pcap -Y "tcp.analysis.retransmission" | wc -l

# 提取 TLS 握手信息(排查证书问题)
tshark -r capture.pcap -Y "ssl.handshake.type == 11" \
  -T fields -e x509sat.uTF8String -e x509af.ipaddress

4.3 批量处理与自动化脚本

以下是我写的一个 Python 脚本,用于批量分析 Nginx 访问日志对应的抓包文件,自动输出慢请求列表:

#!/usr/bin/env python3
"""批量分析 pcap 文件,提取 HTTP 响应时间超过 1s 的请求。"""
import subprocess
import sys
import json

SLOW_THRESHOLD_MS = 1000

def analyze_pcap(filepath):
    cmd = [
        "tshark", "-r", filepath,
        "-Y", f"http.time > {SLOW_THRESHOLD_MS/1000}",
        "-T", "json",
        "-e", "frame.time",
        "-e", "ip.src",
        "-e", "http.request.uri",
        "-e", "http.response.code",
        "-e", "http.time"
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        print(f"Error: {result.stderr}", file=sys.stderr)
        return []
    return json.loads(result.stdout)

if __name__ == "__main__":
    for pcap in sys.argv[1:]:
        print(f"\\n=== Analyzing: {pcap} ===")
        packets = analyze_pcap(pcap)
        for pkt in packets:
            layers = pkt.get("_source", {}).get("layers", {})
            uri = layers.get("http.request_uri", [""])[0]
            code = layers.get("http.response.code", [""])[0]
            time = layers.get("http.time", ["0"])[0]
            src = layers.get("ip.src", [""])[0]
            print(f"  {src} {uri} -> {code} ({time}s)")

使用方式:

python3 analyze_slow.py /tmp/capture_*.pcap

4.4 与 CI/CD 集成

在持续集成中验证网络行为,tshark 是零侵入的选择。例如验证测试期间是否产生了预期的 DNS 查询:

# 测试脚本中启动抓包
sudo tshark -i lo -f "udp port 53" -w /tmp/test_dns.pcap -a duration:30 &
TSHARK_PID=$!

# 运行你的测试...
npm test

# 测试结束后分析
tshark -r /tmp/test_dns.pcap -Y "dns.qry.name contains example.com" | grep -q "example.com" && echo "DNS OK" || echo "DNS FAIL"

kill $TSHARK_PID 2>/dev/null

五、三剑客选型决策表

三种工具不是互斥的,而是互补的。以下是我在不同场景下的选择策略:

场景推荐工具原因
线上服务器紧急抓包tcpdump预装、无 GUI、资源占用低
离线深度分析单个 pcapWireshark图形化、统计图表、协议解码最全
批量处理 100+ pcaptshark脚本化、可编程、自动化
分析 TCP 性能瓶颈Wireshark Stream GraphsRTT/Throughput 可视化无可替代
实时过滤海量流量tcpdump + BPF内核层过滤,性能最高
解密本地 HTTPS 调试Wireshark + SSLKEYLOGFILE图形化展示解密后的 HTTP/2 内容
CI/CD 网络行为验证tshark命令行输出可直接断言

六、常见陷阱与避坑指南

  1. tcpdump 默认截断数据包:tcpdump 默认只抓 68 字节或 262144 字节(版本不同),大报文会被截断。生产环境务必加 -s 0 抓完整包。
  2. Wireshark 过滤器搞混:Capture Filter 是 BPF 语法(tcpdump 同款),Display Filter 是 Wireshark 自己的语法。两者不能混用,初学者最容易卡在这里。
  3. 抓取时磁盘 I/O 成为瓶颈:高流量下,-w 写入磁盘可能丢包。改用 --mmap(新版 tcpdump)或抓包到 tmpfs(内存文件系统)。
  4. 权限问题:tcpdump 需要 root 或 CAP_NET_RAW 能力。容器内抓包要给特权模式,否则看不到任何包。
  5. HTTPS 解密有局限:SSLKEYLOGFILE 方式只能解密使用 ECDHE 密钥交换的会话,不支持 RSA 密钥交换(现代浏览器默认 ECDHE,问题不大)。且无法解密前向保密开启后的历史流量。
  6. tshark 字段名变化:Wireshark 升级后,某些字段名可能变更(如 ssl 变为 tls)。脚本里做版本兼容或正则匹配。

七、快速上手 Checklist

遇到网络问题时,按这个顺序操作,避免抓了一堆无用的包:

  1. 先确认问题可复现:抓包前先明确触发条件,否则大海捞针
  2. 缩小范围:确定是客户端问题、服务端问题还是网络问题。ping、mtr、traceroute 先跑一轮
  3. tcpdump 快速抓取:用精确的 BPF 过滤,只抓相关流量,-s 0 -w 保存
  4. Wireshark 分析:先看 Expert Info,再定位到具体流,最后看包级详情
  5. 提取证据:截图或导出特定包,附带在故障报告中
  6. 验证修复:修复后再次抓包确认问题消失

八、总结

tcpdump 是线上的手术刀,快准狠;Wireshark 是实验室的显微镜,看得深;tshark 是流水线上的机械臂,批量自动化。三者组合,覆盖了从应急到复盘、从手动到自动化的全链路。

抓包能力的提升没有捷径,只有多练。建议你从今天开始:下次遇到任何网络相关的问题,不要急着重启服务,先抓个包看看。坚持十次,你对网络协议的理解会上一个台阶。