抓包这件事,说难不难,说简单也真容易翻车。我第一次打开 Wireshark 的时候,满屏花花绿绿的包在滚,脑子里只有一个念头:这玩意儿到底是给谁看的?后来踩了几次坑才回过味来——Wireshark 本身不是"分析工具",它更像一台显微镜,只负责把链路上跑的东西原封不动地摆在你面前。能不能看出问题,取决于你知不知道要看哪一层、该过滤哪个字段、该拿哪两行做对比。
这篇东西写给三类人:刚装上 Wireshark、点开之后完全没头绪的新手;能抓包但看不懂包、只会截图发群里的同学;以及需要把抓包结果落到具体问题上的运维、后端、嵌入式方向的从业者。我会从安装、界面、捕获过滤器与显示过滤器的区别、帧结构怎么读、TLS 怎么解出明文、RTP 怎么还原成能播的文件、长时间抓包怎么不炸硬盘,一直讲到我个人踩过的那些坑。全部是能直接抄作业的操作,不玩玄学。
1. 动手之前先想清楚:抓包到底在解决什么问题
1.1 三类只有抓包能回答的问题
很多人学 Wireshark 的路径是反的——先学工具,再找问题。正确顺序是先搞清楚哪类问题必须靠抓包,剩下的交给日志和监控。我的经验是,真正非抓包不可的问题只有三类。
第一类是**"到底有没有发出去 / 有没有收到"**。应用层日志说"请求已发送",对端说"我没收到",双方各执一词。这时候只有在中间某台机器的网卡上抓一份,看这一帧是不是真的出网卡了。我遇到过最典型的情况:客户端 TCP 连接建了,请求也写了,但对端回的是 RST。看应用日志完全正常,看抓包才知道是中间某台设备的端口映射指错了。日志永远告诉你"我调用了发送接口",抓包才告诉你"这个字节真的上链路了吗"。
第二类是**"延迟和丢包发生在哪一段"。请求总耗时 3 秒,应用日志只能告诉你"从发起请求到收到响应一共 3 秒",但其中 2.8 秒是握手阶段的往返,还是服务端处理慢,还是中间有重传?这个答案只能从frame.time_delta、tcp.analysis.retransmission这些字段里读出来。抓包最大的价值不是看内容,是看时序**。
第三类是协议实现层的差异。双方都号称"标准实现",结果一方发的包字段填错了、标志位设反了、长度算错了。这种问题文档里查不出来,只能把两边的包摆在一起逐字节比。
注意:如果你的问题属于"业务逻辑不对""数据库查询慢""某个接口返回 500",先去看应用日志和链路追踪,别急着上抓包。抓包是最后一道武器,不是第一道。
1.2 为什么选 Wireshark,而不是浏览器 F12 或 curl
有人会问:浏览器 F12 的 Network 面板不就能看请求吗,为什么要抓包?差别在层级。F12 看到的是已经由浏览器应用层处理完的内容——它自动解压、自动跟随重定向、隐藏了 TCP 层的一切细节。而抓包看到的是网卡上的原始字节:TCP 有没有分片、有没有重传、TLS 握手的每个扩展字段是什么、HTTP/2 的帧是怎么切的。F12 是"菜单",抓包是"后厨"。
curl -v之类的命令行工具也一样,它只覆盖它自己发起的流量。而 Wireshark 抓的是网卡上的全部流量(在你没加捕获过滤器的情况下),包括那些你没意识到存在的东西:后台的 ARP 广播、组播发现、心跳、甚至某个后台服务偷偷重连的痕迹。我在排查一个"设备偶尔失联"的问题时,就是靠抓包发现了设备每隔 30 秒发一次组播发现包,而某台交换机把组播泛洪压住了。
1.3 抓包前的三项确认:网卡、权限、流量路径
动手之前必须确认三件事,否则你抓到的可能是"空文件"。
网卡选对了吗。一台机器上通常有物理网卡、虚拟网卡、回环网卡、蓝牙网卡、甚至容器网桥。你要抓的流量走哪张卡,就得选哪张。要抓本机自己和自己通信(比如本地起了个服务,另一个本地进程去连),那得选回环接口——Windows 上是 Npcap Loopback Adapter,Linux 上是lo,macOS 上是lo0。这一点新手最容易漏:抓了半天一个包没有,就是因为流量根本没走物理网卡。
权限够不够。Linux/macOS 下抓包需要原始套接字权限,普通用户直接开 Wireshark 会提示没有权限。后面 2.2 会讲正确的授权方式,别直接sudo wireshark了事。
流量路径想清楚了吗。这是最容易被忽略的一点。如果客户端和服务器之间隔着一台交换机,你在客户端抓包,只能看到客户端发出去和收到的;中间的丢包、乱序、TTL 被改,你是看不到的。想看到"中间那段",要么在链路上做端口镜像,要么在中间设备本身上抓,要么用带时间戳的分布式抓包做对比。**先画一张流量路径图,标出你打算在哪一点下探针,再动手。**这张图能省掉你一半的返工。
2. 从下载安装到抓到第一个包
2.1 Windows 安装:Npcap 那一步别无脑下一步
Windows 上的安装包从官网拿,安装过程真正需要动脑的只有两个地方。
第一是Npcap的安装选项。Wireshark 安装程序会自动带着 Npcap 一起装,中间会弹出一个独立窗口问你要不要勾选几项。我的建议是:Support raw 802.11 traffic这项,只有你真的要抓 Wi-Fi 管理帧才勾,否则别勾——它会额外装一个无线网卡驱动,有些无线网卡驱动装完之后会和厂商驱动打架,导致连不上 Wi-Fi。Install Npcap in WinPcap API-compatible Mode这项,如果你机器上有其他老工具依赖 WinPcap,建议勾上,避免装完之后那个老工具直接报错找不到驱动。
第二是USB 抓包组件 USBPcap。默认是勾选的,如果你不打算抓 USB 和通过 USB 的蓝牙流量,可以取消,能少一层驱动。真正要抓蓝牙 HCI 的时候再补装也不迟。
安装完第一次启动,Wireshark 会让你选一个配置文件(Profile),默认的 Default 就行。不要在这里改配置,先能抓到包再说。我见过不少人第一次就把界面配色、列宽、时间格式全改了,结果后面看教程完全对不上,然后又找不到怎么恢复。
2.2 Linux 与 macOS:权限问题的正解
Linux 上直接sudo wireshark是很常见的做法,但它有两个问题:一是 Wireshark 的图形界面会以 root 身份运行,某些插件和配置文件会写到 root 的家目录下,你自己的配置反而读不到;二是 GUI 以 root 跑本身不是好习惯。
正规做法是给抓包相关的二进制授予原始套接字能力,判断你需要用dumpcap和wireshark两个程序。发行版通常有现成的包配置方式,走一遍之后把当前用户加进对应的用户组,注销重新登录即可。做完之后普通用户就能直接打开 Wireshark 并看到网卡列表了。
macOS 上的 GUI 抓包需要安装底层抓包库的支持组件,装完之后通常还会需要重启一次。如果你更愿意走命令行,tshark在 macOS 上配合sudo是最省事的路径,抓文件下来再用 Wireshark GUI 打开分析,这条链路特别适合远程服务器和 macOS。
实操心得:永远不要在服务器上开 GUI。服务器上老老实实用
dumpcap或tshark抓到文件,再拷回本地用 Wireshark 打开分析。原因很简单——GUI 会占用大量内存去解析和着色,一个几 GB 的抓包文件在服务器上打开,能把内存吃光,顺手把你的服务也带走。
2.3 界面速览:只需要先记住五块区域
Wireshark 主窗口看起来很复杂,但真正需要用的就五块。
| 区域 | 位置 | 作用 | 新手要不要立刻用 |
|---|---|---|---|
| 网卡列表 / 工具栏 | 顶部 | 选网卡、开始停止、保存 | 立刻要 |
| 显示过滤器栏 | 工具栏下方绿色条 | 输入显示过滤器,决定"看哪些包" | 立刻要 |
| 数据包列表 | 上半部分 | 一行一个包,按序号排列 | 立刻要 |
| 数据包详情 | 左下半部分 | 展开的协议树,逐层字段 | 立刻要 |
| 数据包字节 | 右下半部分 | 十六进制与 ASCII 对照 | 第二阶段再熟悉 |
数据包列表里的列是可以在"列首选项"里增删的。默认那几列——序号、时间、源、目标、协议、长度、信息——信息量其实不够。我一般会固定加三列:frame.time_delta_displayed(相对上一显示包的时间差)、tcp.stream(TCP 流编号)、udp.stream(UDP 流编号)。为什么是这三列?因为排查问题时你 90% 的时间都在回答两个问题:"这个包属于哪条连接?"以及"它距离上一个包过了多久?"这两列直接把它算好摆在你面前,比每次去展开详情里翻要快得多。
2.4 打不开、看不到网卡、一开就卡:三类启动故障排查
打不开(闪退或卡在启动画面),绝大多数是配置文件损坏。Wireshark 的配置目录在用户目录下,把它整体改名(相当于重置为出厂状态),再启动试试。如果改名后能启动,说明就是配置问题,你可以逐个把旧配置搬回来,定位到具体是哪个文件(通常是colorfilters或自定义的列配置)惹的祸。另一种可能是抓包驱动没装好,重装一遍抓包驱动通常能解决。
看不到网卡,分两种情况。一种是驱动层没装上(Windows 上就是 Npcap 没装或装失败),另一种是权限不够(Linux 上是没做授权)。前者的判断方法很简单:打开"捕获选项"窗口,如果网卡列表是空的,或者只列了极少数几个条目,基本就是驱动问题。
一开就卡住,这是问得最多的问题之一。我在 6.1 里会详细讲,这里先说最快的解法:打开"捕获选项",把"实时更新数据包列表"取消掉,改抓完再显示。这个选项会让 Wireshark 一边抓一边把每个包塞进列表并应用显示过滤器和着色规则,流量一大,CPU 全耗在渲染上,抓包本身反而丢包了。
3. 过滤器体系:捕获过滤器和显示过滤器是两码事
这是新手最容易混淆的概念,也是我见过最多人卡住的地方。捕获过滤器作用在抓包之前,用的是 BPF 语法,丢掉的包永久丢失;显示过滤器作用在抓包之后(或打开文件之后),用的是 Wireshark 自己的字段语法,丢掉的包还在文件里,只是不显示。两者语法完全不通,写错了都会报红。
3.1 捕获过滤器:BPF 语法,抓之前就把垃圾挡在门外
什么时候该用捕获过滤器?答案是流量远大于你想看的量的时候。在服务器上抓包,全量抓一个小时的流量可能有几十 GB,而你只关心某个端口,这时候用捕获过滤器是最明智的。
BPF 的语法结构是"限定词 + 逻辑组合",常见写法如下。
| 需求 | 捕获过滤器写法 | 说明 |
|---|---|---|
| 只看某台主机 | host 192.168.1.100 | 源或目标任一为该地址 |
| 只看某端口 | port 8080 | 源或目标任一为该端口 |
| 只看 TCP 某端口 | tcp port 443 | 加协议限定更精确 |
| 只看某个网段 | net 10.0.0.0/8 | 整个网段 |
| 只看指向某地址的流量 | dst host 192.168.1.1 | 注意方向限定词 |
| 排除某类流量 | not arp and not icmp | 抓之前先减负 |
| 只要广播和组播 | ether broadcast or ether multicast | 排查发现协议时有用 |
BPF 里有个细节容易踩:port 80会同时匹配源端口 80 和目标端口 80,如果你只想看"发往 80 端口"的请求,得写dst port 80。另外 BPF 不支持分片之后的字段精确匹配,比如你写port 80,一个分片的后续片可能因为没有端口字段而被漏掉。排查分片相关的问题时,别用端口过滤,改用host。
注意:**捕获过滤器一旦写错方向,你会丢掉最关键的那一半包。**我习惯的做法是:如果不是磁盘或性能压力极大,先用宽一点的过滤器(比如只写
host x.x.x.x),把原始数据留全,用显示过滤器去筛。数据留全了,后面想改主意还来得及;抓的时候滤掉了,就只能重抓。
3.2 显示过滤器:字段名 + 运算符 + 值的三段式
显示过滤器是真正每天都用的东西,它的结构极其规整:协议.字段 运算符 值。运算符分两类,比较类有==、!=、>、<、>=、<=,文本类有contains、matches(正则)、in。逻辑组合用and、or、not,括号可以嵌套。
几个必须刻进肌肉记忆的常用写法:
ip.addr == 192.168.1.100 # 源或目标是这个 IP tcp.port == 443 # TCP 443 http.request # 只看 HTTP 请求 http.request.method == "POST" # 只看 POST tcp.flags.syn == 1 and tcp.flags.ack == 0 # 只看握手第一个 SYN dns.qry.name contains "example" # DNS 查询名包含某串 tls.handshake.type == 1 # TLS Client Hello udp.port in {5004, 5005, 5006} # 命中多个端口之一 frame.len > 1500 # 超长帧(jumbo 相关) !arp and !icmp # 排除 ARP 和 ICMP几个容易忽略但特别好用的技巧。
contains和matches的区别。contains是字节序列包含,对十六进制也有效;matches是正则,性能差一些但表达力强。要找某个字符串出现在任意位置,用frame contains "GET /api"比一层层展开快得多。
in集合运算。Wireshark 4.0 之后集合写法支持得很好,ip.addr in {10.0.0.1, 10.0.0.2}一行顶三行。
任意字段存在性判断。想知道"哪些包带了 TLS 的 Server Name 指示",写tls.handshake.extensions_server_name就行——只要这个字段存在,包就会被留下。这个写法在排查"某个扩展为什么没生效"时非常好用。
3.3 高频筛选需求实操(含 UDP 前后包时间间隔)
我把被问得最多的几个具体需求单独拎出来,每个都给完整做法。
需求一:UDP 前后两包的时间间隔怎么筛出来。
这是典型需求——比如评估音视频流的抖动,想知道同一路 UDP 流里相邻两个包的间隔。做法有两步。
第一步,先把范围缩到你关心的那条流上,比如udp.port == 5004。第二步,不要自己算,让 Wireshark 帮你算:在数据包列表的列标题上右键,进入列首选项,新增一列,字段名填frame.time_delta_displayed。这一列的含义是"距离上一条被显示的包过了多久"。注意"被显示"这三个字——它只统计通过显示过滤器的包,所以只要你把过滤范围限定在一条流上,这一列就是这条流相邻两包的真实间隔。
如果你要批量导出来做统计(比如算 P99 抖动),GUI 就不合适了,用命令行:
tshark -r udp.pcapng -Y "udp.port==5004" \ -T fields -e frame.number -e ip.src -e ip.dst \ -e udp.srcport -e udp.dstport -e frame.time_delta_displayed \ -E header=y -E separator=, > udp_delta.csv导出来的 CSV 直接扔进表格软件或者写几行脚本算分位数,比在 GUI 里一个个看靠谱得多。
需求二:只看某个以太网发送源的数据包字节内容。
这个需求拆成两半:筛选和查看字节。筛选用eth.src == aa:bb:cc:dd:ee:ff。查看字节有几个层次:选中包之后看右下的"数据包字节"面板,那是整个帧的原始十六进制;如果只想看某个字段的字节,在协议树里选中那个字段,对应字节会在下方高亮,这时候右键选"复制 → 作为十六进制转储",就能把这一段粘到工单里。要导出成文件,用"文件 → 导出指定分组字节流",可以按范围导出。
需求三:只看 HTTP 里的某个错误响应。
http.response.code >= 400一步到位。要再叠加域名,http.host contains "api.example"。
需求四:找出所有重传。
tcp.analysis.retransmission是 Wireshark 的专家信息字段,它会自动识别重传并打标。同类字段还有tcp.analysis.fast_retransmission(快速重传)、tcp.analysis.duplicate_ack(重复确认)、tcp.analysis.zero_window(零窗口)。这几个字段串起来,基本就能还原出一条 TCP 连接的"健康状况"。
3.4 过滤器的经典坑
坑一:把捕获过滤器语法写在显示过滤器栏里。你写tcp port 80到显示过滤器栏,它会报红。显示过滤器必须写tcp.port == 80。反过来,捕获过滤器栏里写tcp.port == 80也会报错。记住:带==的是显示过滤器。
坑二:字符串值不加引号。http.request.method == POST是错的,必须"POST"。而数字值加了引号,有些情况下也能工作但语义变了,建议严格按字段类型来。
坑三:ip.addr和ip.src混用导致的"包少了一半"。ip.addr是双向匹配,ip.src和ip.dst是单向。排查"请求为什么没回"的时候,你需要的往往是ip.addr;排查"谁在扫我"的时候,你需要的通常是ip.src。
坑四:显示过滤器写得太宽松,导致看起来"丢包"。显示过滤器的计算是在所有包上做的,如果表达式里带了耗时的正则,大文件上会明显卡顿。这时候先用捕获过滤器缩小范围,或者拆成两步筛。
4. 看懂一个包:从以太网帧头一路拆到应用层
4.1 帧结构的四层解剖
选一个包,展开数据包详情面板,从上往下就是一条完整的封装链。我用一个 HTTP over TCP over IPv4 over Ethernet 的包举例。
| 层级 | 关键字段 | 排查时看什么 |
|---|---|---|
| Frame(帧元信息) | 帧号、捕获时间、帧长、捕获长度、协议 | 判断有没有被截断、时间基准是什么 |
| Ethernet II | 源 MAC、目的 MAC、类型 | 判断流量从哪来、是不是走了错误的二层出口 |
| Internet Protocol v4 | 源 IP、目的 IP、TTL、标识、分片标志 | 判断路由方向、有没有分片、TTL 是否异常 |
| Transmission Control Protocol | 端口、序号、确认号、标志位、窗口、选项 | 判断连接状态、重传、窗口大小、MSS 协商 |
| Hypertext Transfer Protocol | 方法、URI、响应码、头部 | 判断业务层行为 |
读这一棵树有个顺序上的讲究:从下往上读,从外往里读。先确认二层是不是发到了正确的 MAC,再确认三层 IP 方向对不对,再看四层 TCP 状态,最后才看应用层内容。很多人上来就直接展开 HTTP,看请求头里的参数,一旦发现"请求参数不对",其实问题可能早在 TCP 层就注定了——比如连接是被复用的,上一个请求的响应还没读完就发了下一个,导致服务端解析错位。这种情况只看 HTTP 层永远看不出来。
MAC 地址这一层有个实用技巧。默认情况下 Wireshark 只显示 OUI 部分对应的厂商名,如果你想看得更清楚,可以在以太网协议首选项里打开"解析厂商名称"。在排查"这台机器到底连到了哪台交换机口"这种问题时,把 MAC 和厂商名对照着看,比光看一串十六进制友好得多。
4.2 为什么只显示 520 字节?2090 字节怎么才能看全
这个问题被问了无数次,根源在Frame 这一层里的两个长度字段。展开任意一个包的 Frame 层,你会看到类似这样的内容:Frame is 2090 bytes on wire,紧接着2090 bytes captured。第一个是链路上实际的长度,第二个是被保存下来的长度。如果第二个数小于第一个数,说明这个包被截断了。
为什么会被截断?因为抓包的时候可以设置一个"每个包最多抓多少字节"的上限(通常叫 snaplen)。老版本的默认值偏小,有些采集设备或镜像口为了避免占用带宽,也会主动设一个较小的值。当上限设成 520 这样的数字时,所有超过 520 字节的包都只留前 520 字节,剩下的丢掉。你在"数据包字节"面板里就只能看到 520 字节。
怎么改成能看全 2090 字节?分两步:
第一步,改抓包时的上限。在"捕获选项"里找到"限制每个数据包捕获的字节数"(Limit each packet to),把值改成 0 或者把它关掉。填 0 的含义就是"不限制"。注意:这个设置必须在开始抓包之前设好,抓完之后的文件没法恢复被丢掉的字节。
第二步,如果你已经拿到了一个被截断的文件,那就没办法了——丢掉的字节在物理上不存在。唯一的做法是重新抓。所以养成习惯:抓包前先确认上限设置,别用默认值直接开抓。
再说 2090 这个数字本身。普通的以太网帧(不含 VLAN 标签)最大是 1518 字节,带 VLAN 标签是 1522。2090 已经超出了这个范围,说明你抓到的很可能是jumbo frame(巨帧)。巨帧需要链路上每一环都支持(网卡、交换机、对端),任何一环不支持就会触发分片或直接丢弃。这时候你的排查重点不是 Wireshark 的设置,而是链路配置:网卡的巨帧开关、交换机端口的 MTU、对端是否也开了。抓包只能告诉你"这个帧有 2090 字节",它不会告诉你为什么对面收不到。
实操心得:看到"bytes on wire"和"bytes captured"两个数字不一致,第一时间想到 snaplen;看到帧长超过 1518,第一时间想到 MTU 和巨帧。这两个反应能帮你快速分类问题,不至于在 Wireshark 的设置里瞎翻。
4.3 时间列怎么调:相对时间、绝对时间与 Delta
时间列是抓包分析里信息量最大的一列,但默认的"绝对时间"其实是三种时间视图里最不好用的。
绝对时间(自 1970 年起的秒数)适合做跨设备的时间对齐。比如你在客户端和服务器各抓一份包,用绝对时间才能把两边的事件对应到同一个时间轴上。做分布式排查时,先把两台机器的时钟同步好(这步不做,后面的对齐全是白费),再看绝对时间。
相对时间(自第一个包起)适合看单次会话的整体节奏。你想知道"从握手到响应一共多久",切到相对时间最直观。
Delta 时间(距上一个包的间隔)适合看细粒度抖动和超时。TCP 的重传超时、UDP 的抖动、心跳是否按时到达,全都要看这个。我强烈建议把它固定成一列常驻,前面 2.3 里已经提过。
切换方式在"视图"菜单里,三选一。另外还有一个容易被忽略的选项:时间精度的显示格式。默认是秒到小数点后若干位,但在排查高精度场景(比如音视频同步、工业总线)时,你可能需要微秒甚至纳秒精度,这个也在视图菜单里调。
4.4 追踪流与导出对象:把"包"还原成"内容"
单看一个个包效率太低。Wireshark 有两个功能能把散落的包拼回完整内容。
Follow Stream(追踪流):在任意一个包上右键,"追踪",选择对应的流。Wireshark 会把属于同一条连接的所有数据按顺序拼起来,分色显示两个方向的内容。TCP 流、UDP 流、HTTP 流、TLS 流、HTTP/2 流都支持。看协议交互的时候,这个视图比包列表强太多——你能一眼看到请求和响应的完整文本,还能直接"另存为"导出原始数据。
导出对象(Export Objects):文件菜单下,能自动把 HTTP、SMB、TFTP 等协议传输的文件还原出来存到本地。排查"下载的文件损坏"这类问题时,直接导出对象再和源文件做校验,比看包快得多。
注意:追踪流视图里的内容有时会被 Wireshark 标成"可能不完整"(比如丢包导致数据缺失)。这时候别急着下结论,回到包列表去看有没有重传标记和乱序标记。
5. 六个能直接抄的实战场景
5.1 TCP 握手、重传与窗口:定位"慢"和"断"
握手分析。过滤tcp.flags.syn == 1,会看到每个连接的第一个 SYN 和 SYN-ACK。正常的握手是三次:SYN、SYN-ACK、ACK。如果只有 SYN 没有 SYN-ACK,说明请求发出去了但对端没回,问题在对端或者中间链路。如果收到的是 RST,说明对端明确拒绝,通常是端口没开或者被防火墙拦了。这两种情况的处理方向完全相反,所以第一步永远是先确认"没回"还是"被拒"。
重传分析。重传意味着"我发了但没收到确认"。过滤tcp.analysis.retransmission,结合 Delta 时间列看间隔。间隔接近固定的超时时间(比如 200ms、1s 这种阶梯值),说明对端一直没确认,属于真正的丢包;间隔很短且集中在某几个包上,可能是乱序造成的"假重传"——Wireshark 只是看到同一个序号又出现了一次,实际上只是包走岔路了。这两种要分开处理:真丢包去查链路质量,假重传去查多路径和负载均衡。
窗口分析。过滤tcp.analysis.zero_window,如果有,说明接收方缓冲区满了,发送方被迫停发。这时候你要看的是接收方的应用有没有及时读数据——这往往是应用层处理慢的信号,而不是网络问题。
5.2 解密 TLS 看明文:SSLKEYLOGFILE 的正确姿势
排查自己开发的程序时,经常需要看 TLS 里的明文。这里有一个前提必须说清楚:只有你自己有权限、且属于你自己或你有明确授权调试的流量,才去做这一步。抓别人的加密流量去解密,不是技术问题,是别的问题。
技术上,Wireshark 支持两种解密方式。
第一种是用密钥日志文件(推荐,适用于 TLS 1.3 和所有前向保密算法)。原理是让客户端把每次会话的密钥材料写到一个文件里,Wireshark 读这个文件还原会话密钥。操作方法:
Windows 下先设一个环境变量,指向你准备存放密钥日志的路径:
set SSLKEYLOGFILE=C:\temp\sslkey.log类 Unix 系统下:
export SSLKEYLOGFILE=~/.sslkey.log关键的一步:设置完环境变量之后,必须完全退出目标程序(浏览器要确认所有进程都关掉,包括后台驻留的),然后再从设置过环境变量的终端里启动它。否则环境变量不会被继承,日志文件根本不会生成。这一步我踩过不止一次坑——文件一直是空的,以为是 Wireshark 的问题,其实是启动方式不对。
然后在 Wireshark 的"首选项 → 协议 → TLS"里,把"(预)主密钥日志文件名"指向这个文件。设置好之后再打开抓包文件,原本加密的 TLS 记录就会自动变成可读的明文,过滤http2或http就能看到内容了。
第二种是用服务端私钥。在 TLS 首选项里配置私钥文件。但这种方式只对使用 RSA 密钥交换的老式套件有效,现代的 TLS 1.3 和所有使用前向保密(ECDHE)的套件都用不了。所以别把希望寄托在私钥上,老老实实用密钥日志。
实操心得:如果配好了密钥日志但内容还是密文,按这个顺序查:文件里有没有内容(没有就是环境变量没生效)、文件里的时间范围和抓包时间对得上吗(对不上就是用了旧文件)、TLS 首选项里路径有没有写对、协议版本和密码套件是不是支持。这四步查完,99% 的情况能定位。
5.3 RTP 流转成可播放的音视频
Wireshark 对 RTP 有专门的支持,能把媒体流还原成文件。
路径是"电话 → RTP → 显示所有流",会列出抓到的所有 RTP 会话,每条有源、目标、丢包率、抖动、最大间隔等统计。选中一条流,点"分析",可以看这个会话的详细信息,点"播放流"能直接听(如果编码支持)。要导出文件,用"保存载荷"功能。
导出的载荷是裸码流,没有容器封装,所以一般不能直接双击播放,需要过一手转码工具。常见两种:
# G.711 μ-law 音频,8kHz 单声道 ffmpeg -f mulaw -ar 8000 -ac 1 -i payload.au payload.wav # H.264 裸流转成 mp4 容器 ffmpeg -f h264 -i video.raw -c copy video.mp4几个容易踩的坑:一是丢包会让导出的文件中间断裂,音视频会出现明显的卡顿或花屏,这本身就是有用的信息——它证明了丢包确实影响了体验。二是如果音频是多路混音或者用了非常规编码,转换参数要对上采样率和声道数,参数写错会变成快放或慢放。三是"播放流"功能依赖 Wireshark 自带的解码支持,不支持的时候只能走导出加转码这条路。
丢包率是这里最有价值的指标。RTP 统计里会直接给你丢包率和抖动值。我遇到过"通话偶尔卡一下"的问题,抓包一看丢包率 0.5%,看着不高,但抖动值波动很大,说明是链路抖动而不是单纯丢包。这个区分决定了你去查交换机 QoS 还是去查带宽占用。
5.4 长时间抓包:环形缓冲与自动切文件
长时间抓包最怕两件事:硬盘被写满,和一个几个 GB 的文件打开就卡死。解决办法都是自动切文件 + 环形缓冲。
图形界面里在"捕获选项 → 输出"标签页,勾选"自动创建新文件",可以按文件大小或按时间切分。再加一个"环形缓冲区",指定保留几个文件——比如设成"每 100MB 切一个,保留 20 个",那最多占 2GB 硬盘,新的覆盖旧的。
命令行下我更推荐用dumpcap,它比tshark更适合长时间抓包,因为它做的工作更少:
dumpcap -i eth0 -s 0 \ -b filesize:102400 -b files:20 \ -w /data/cap.pcapng这里的-s 0就是前面说的"不限制每包长度",-b filesize:102400是每个文件 100MB 切一个,-b files:20是最多保留 20 个文件。这样跑一整天也不用担心爆盘。
注意:**做长时间抓包之前,务必先确认硬盘剩余空间和写入速度。**我见过因为写入磁盘速度不够导致 dumpcap 丢包的案例——抓包文件里会出现 Wireshark 自己上报的"丢包"提示(在状态栏或者统计信息里能看到)。所以长时间抓包不要写网络盘或者慢速 U 盘,写本地 SSD。
另外,长时间抓包一定会遇到"我需要的是昨天下午三点那一刻的包"。解决方式是在时间轴上打标记:抓到问题复现的时候,用 Ctrl+E 在捕获过程中插入一个标记包,后面找起来直接搜标记就行。这个小技巧能省掉大量翻找时间。
5.5 非以太网场景:蓝牙 HCI 日志与工业协议
Wireshark 不只抓以太网。很多人不知道它还支持蓝牙、USB、以及通过插件扩展的各类工业协议。
蓝牙。最省事的路径不是直接在 Wireshark 里抓,而是利用手机自带的 HCI 日志功能。在开发者选项里开启蓝牙 HCI 侦听日志,复现问题,然后把日志文件(通常在设备存储根目录下,名字是btsnoop_hci.log)拷出来,用 Wireshark 打开。这个文件的格式 Wireshark 原生支持,能看到 HCI 命令、事件、以及上层的 L2CAP 和 ATT 数据。排查"蓝牙设备频繁断连""GATT 特征值读不到"这类问题的效率,比自己写日志高一个量级。Windows 上如果要在 PC 端抓,需要装 USB 抓包组件,然后在设备列表里选对应的 USB 无线网卡设备。
工业协议。很多专用工业协议(比如轨道交通领域的 TRDP)不在 Wireshark 官方主程序里,需要自己装解析器。通常有两条件:一是协议维护方会提供一个源码插件,自己按 Wireshark 插件 ABI 编译成动态库放进插件目录;二是自己写一个 Lua 解析脚本,放在个人配置目录下的插件文件夹里。这里最大的坑是版本匹配——插件编译时依赖的 Wireshark 版本、与你实际运行的版本、以及插件 ABI 版本三者必须一致,不一致的表现通常是"插件加载了但协议树里什么也不显示",或者干脆报加载失败。我的建议是固定一个大版本,别追新。
5.6 可视化:IO Graph、会话统计与专家信息
单看包列表容易只见树木不见森林,这三个统计功能建议养成习惯性看一眼。
IO Graph(吞吐图):在"统计"菜单里。它把流量按时间画成曲线,可以按显示过滤器拆成多条线。看"某个时刻流量突然掉零"这类现象特别直观。比如排查一次短时中断,把业务端口和心跳端口各画一条线,如果两者同时掉零再同时恢复,那基本可以确定是链路层面的问题,而不是应用的问题。
会话统计(Conversations):列出所有会话和它们的字节数、包数、持续时间。排序一下,立刻能看出谁在占带宽。这个功能在排查"网络为什么这么慢"时是第一步——先看谁在占,再看它凭什么占。
专家信息(Expert Information):Wireshark 把整个抓包文件里识别出的异常按严重程度分级列出来,包括校验和错误、重传、连接重置、协议警告。这个功能有个前提:它依赖 Wireshark 自己的协议解析和一致性检查,所以它报的"错误"不一定是真错误,可能只是解析器不认识某个扩展。得到一个可疑项之后,一定要跳回对应的包去看实际内容,别拿专家信息当结论。
6. 稳定性与性能:为什么它会卡住
6.1 卡住的四个高频原因
原因一:实时更新列表。前面提过,这个选项让 Wireshark 边抓边渲染,流量一大就卡。解决方式是关掉它,或者直接用dumpcap抓、抓完再打开。
原因二:名称解析。默认可能开着网络名称解析和 MAC 名称解析,每遇到一个新 IP 就去查一次域名,大量查询会把整个过程拖慢甚至卡死。在"视图"菜单里把这两项关掉,速度立刻回来。很多人抱怨"Wireshark 打开文件特别慢",八成就是这个原因。
原因三:文件太大。一个几 GB 的抓包文件,Wireshark 要把它整个读进内存并建立索引。这种文件不要硬开,先用命令行做裁剪。
原因四:着色规则和列计算。自定义的着色规则和大量自定义列(尤其是带函数的列,比如各种 Delta 时间)会增加每个包的渲染成本。在分析大文件之前,可以先切到一个干净的配置 Profile。
6.2 大文件处理:tshark 与 editcap 的组合拳
拿到一个大文件,第一步永远是先看它是什么:
capinfos big.pcapng这个命令会告诉你文件时长、包数量、平均速率、有没有被截断、有没有丢包标记。看完这些信息,你就知道该往哪个方向处理了。
第二步是按需裁切。比如只保留某个时间段的包:
editcap -A "2024-05-01 10:00:00" -B "2024-05-01 10:05:00" big.pcapng slice.pcapng或者只保留前 10 万个包:
editcap -r big.pcapng small.pcapng 1-100000第三步是用tshark做字段级提取,而不是用 GUI 去看。举个例子,你想统计某个 IP 在一小时内每分钟的包数量:
tshark -r big.pcapng -Y "ip.addr==192.168.1.100" \ -T fields -e frame.time_epoch > ts.csv拿到时间戳再写几行脚本按分钟聚合,比在 GUI 里翻页快得多。
实操心得:把 tshark 当成"抓包数据的 SQL"。凡是"按条件筛、按字段取、按维度聚合"这类需求,一律走命令行;只有"看具体某一个包长什么样"才开 GUI。这个分工能让你的分析效率提升好几倍,也避免了跟大文件搏斗。
6.3 长时间抓包的资源规划
长时间抓包要算三笔账:硬盘、内存、CPU。
硬盘:按链路速率估算。千兆链路上满负荷跑,一秒大约是 125MB,一小时就是 450GB。当然实际业务流量通常远低于满负荷,按实测的峰值速率乘上时间,再留一倍余量。如果算下来硬盘扛不住,就必须用捕获过滤器砍掉无关流量——这是唯一能实质降低存储量的手段。
内存:只用dumpcap抓包的时候,内存占用很低,因为它是流式写盘,不建索引。用 GUI 实时抓包的时候内存增长就明显了。所以长时间任务一律用dumpcap。
CPU:抓包本身消耗不大,但如果你同时开着统计分析或者实时显示,CPU 会被吃掉。长时间任务里把这些全部关掉。
具体参数上,我常用的组合是每 100MB 或每 10 分钟切一个文件,保留 20 到 30 个。这个组合在千兆环境下大约能覆盖最近 30 分钟到 1 小时的时间窗口,出问题回溯基本够用。如果你们的复现周期更长,就得提高保留数量,同时接受更大的硬盘占用。
7. 常见问题速查与个人避坑经验
7.1 速查表
| 现象 | 最可能的原因 | 处理方式 |
|---|---|---|
| 抓了很久一个包都没有 | 选错了网卡(本机通信要走回环) | 换回环接口,或确认流量实际走哪张卡 |
| 抓到几百字节就断 | 抓包长度上限设小了 | 捕获选项里把限制改成 0,重新抓 |
| 帧长显示超过 1518 | 链路上有巨帧 | 检查网卡、交换机、对端的 MTU 配置 |
| 打开文件特别慢 | 名称解析开着 / 文件太大 | 关掉名称解析;用 editcap 先裁切 |
| 抓包过程中提示丢包 | 写盘速度跟不上 | 换本地 SSD;加捕获过滤器减量;关实时显示 |
| 显示过滤器报红 | 用了捕获过滤器语法 | 改成字段语法,字符串加引号 |
| 解密后还是密文 | 密钥日志没生成或路径不对 | 确认进程重启过、文件有内容、时间对得上 |
| 自定义解析不生效 | 插件与主程序版本不匹配 | 固定大版本,按 ABI 重新编译 |
| 界面打不开或闪退 | 配置文件损坏 | 把配置目录改名重置,再逐步恢复 |
| 抓不到 Wi-Fi 管理帧 | 抓包驱动没开无线模式支持 | 重装抓包组件并勾选对应选项 |
7.2 几条只有踩过才知道的经验
第一条:先确认时间同步,再谈跨设备对比。在两端同时抓包做对比,如果两台机器的时钟差了几秒,你做的所有时序推理都是错的。做分布式排查之前,先把时钟对齐,这一步花的时间远比后面反复怀疑结论要值。
第二条:抓包文件要留元信息。我现在的习惯是每次抓包都在文件名里写清楚"时间-地点-对象-目的",比如0510-officeA-client-to-api-tlsdebug.pcapng。过一周再回头看,没有元信息的抓包文件就是一堆废字节。如果条件允许,在抓包开始时手工插一个标记包,把当前工单号或环境信息写进去。
第三条:不要把"Wireshark 报的错误"当成"真错误"。校验和错误在开启了网卡校验和卸载(checksum offload)的机器上非常常见,因为网卡还没算完校验和,抓包就抓到了。看到校验和错误先看是不是本机发出的包——是的话基本可以忽略。同理,专家信息里的"协议警告"很多只是解析器不支持某个扩展,不代表对端行为异常。
第四条:抓到问题现场之后,第一件事是保存文件。环形缓冲会覆盖旧文件,你在那儿分析的时候,关键的那段可能已经被新流量冲掉了。确认问题复现之后,立刻停止抓包并另存一份。
第五条:别在生产的核心节点上长时间开着 GUI 抓包。抓包会占用 CPU 和内存,万一出问题,影响的是业务本身。核心节点一律用dumpcap写文件,磁盘和权限都单独规划好。
第六条:学会看"没有的东西"。抓包里最值得关注的往往不是出现了什么,而是缺了什么。请求发了但没有对应的响应、握手只有 SYN 没有 SYN-ACK、心跳序列中间少了一拍——这些"缺失"是排查问题最关键的线索,而它们在日志里通常完全体现不出来,因为日志只记录"我做过的动作",不记录"我没做的事"。
最后再说一个小技巧,关于把抓包结果交给别人看。你要发工单或者发群里的,通常不应该是整个抓包文件,而是三样东西:一份筛选后的最小复现文件(用 editcap 裁到只含关键的时间段和会话)、一张关键字段的十六进制转储(选中字段后右键复制为十六进制)、以及一句话说明"在这个包和这个包之间发生了什么"。这三样东西凑齐,对方基本上不用再问你第二遍。我见过太多人甩一个几百 MB 的文件过去,然后两边开始互相等——这种做法浪费的是双方的时间。