Windows 数据包捕获实务——pktmon、netsh trace 与 Wireshark 的分工

· 更新日期: · · Windows, 数据包捕获, pktmon, netsh, Wireshark, 网络, 故障排查, TCP/IP

更新记录(仅首版,2026年08月20日 发布)
首次发布
引用本文(DOI(已登记存档): 10.5281/zenodo.22176163)

以下 DOI 指向先前登记的存档,内容可能与当前正文不同。引用当前正文时,请使用本页网址。

Go Komura(2026)。《Windows 数据包捕获实务——pktmon、netsh trace 与 Wireshark 的分工》。小村软件有限公司。 https://comcomponent.com/zh-CN/blog/windows-packet-capture-pktmon-netsh-wireshark/

DOI(已登记存档)
10.5281/zenodo.22176163
DOI(上次登记版本)
10.5281/zenodo.22176164

“业务应用的通信每月失败几次。日志里只有‘超时’。服务器端也没有报错,复现条件同样不清楚。”这是通信故障排查中常见的状况。

这时想知道的是,究竟是根本没连上,还是连上之后响应停了。同样是超时,接下来该查的地方并不相同。

应用日志里留下的,只有应用“决定要写下来的那部分”。仅凭“超时”这个结果,无法区分是 SYN 没有得到响应,是在已建立的连接上服务器不作声了,还是被 RST 断开了。

去查它下一层的实际流经线路的数据包,这就是数据包捕获。Process Monitor 是从下一层观察对文件和注册表的访问,而这里看的是通信的下一层。想确认数据包是否送达了目的地时,第 7 章讲的两端同时采集就很关键。

应用日志下一层的数据包展示应用日志只会留下决定要写下来的内容,而 SYN 是否没有响应、建立连接后是否不作声、是否被 RST 断开、究竟有没有送达,只会留在实际流经线路的数据包里看下一层应用的日志只留下决定要写的内容结果只有“超时”一句话实际流经线路的数据包SYN 没有响应?建立后不作声?被 RST 断开?送达目的地了?

图1:日志里留下的只是结果,超时的细分只存在于下一层的数据包里。

即使遇上“客户服务器装不了 Wireshark”,也不必放弃采集。就算因为变更管理或安全策略无法添加软件,Windows 也自带了 pktmon 和 netsh trace 这两种采集手段。

基本做法是这样的分工:在现场用自带工具采集,在自己手边用 Wireshark 阅读。把采集和分析当成两件独立的工作来安排,即使现场有安装限制,调查也能推进下去。

本文面向中小企业的信息系统负责人和 Windows 应用开发者,梳理 pktmon、netsh trace 与 Wireshark 的分工,以及各自的实务步骤。从环回通信的陷阱、在客户端还是服务器端采集的判断、如何面对 TLS 下看不到内容的问题,一直到与应用日志的比对,全部基于 2026 年 8 月时点的一手资料来讲解。

按遇到的问题来读

遇到的问题 首先要确认的事 阅读位置
客户服务器上装不了 Wireshark 用自带工具采集、在手边分析的分工 工具的选法、pktmon 的步骤
想采集重启刚结束时的通信 netsh trace 的场景与持续采集 netsh trace 的步骤
捕获采到了,却不知道从哪里读起 显示过滤器与 TCP 的 4 个确认点 用 Wireshark 阅读的方法
发往 localhost 的通信显示不出来 采集用的适配器,以及 IPv4 和 IPv6 的混淆 环回通信
看得到重传,却不知道是在哪里丢的 两端同时采集与时间差的记录 采集位置与时间同步
不知道什么时候会发生 定好容量的环形缓冲区,以及发生后的停止步骤 长时间采集
想调查 TLS 通信/想把采集文件交出去 不解密也能知道的范围,以及机密信息的处理 TLS 的看法、与日志的比对和共享

第一次读的话,请先把握第 2 章选工具、第 3~4 章采集、第 5 章阅读这条主线。第 6~8 章讲采集条件和观测范围上的注意事项,第 9 章讲结合应用日志得出结论的步骤。

1. 先说结论

采集和分析可以交给不同的工具

在现场用 pktmon 或 netsh trace 采集,转换成 pcapng 后在手边的 Wireshark 上分析。两者的输出都是 ETL,原样是打不开的。pktmon 用 pktmon etl2pcap,netsh trace 用 Microsoft 出品的开源工具 etl2pcapng。12

选工具的顺序是先 pktmon,不够再上 netsh trace,协议分析交给 Wireshark。Microsoft 的调查指南给出的也是这个流程。3

采集前先定好要留下的信息和观测的位置

pktmon 从 Windows 10 / Windows Server 2019 起随系统内置,按注册过滤器→开始→停止→转换这 4 个步骤使用。它独有的长处是能看出数据包是在堆栈内的哪个位置被丢弃的,以及丢弃原因。不过,默认留下的只有开头 128 字节。要读到内容,就在开始时指定 --pkt-size 0。456

netsh trace 是更早就有的自带工具。它以场景为单位把一组 ETW 提供程序捆在一起,能同时采集数据包和 Windows 内部的事件。要跨越重启采集就用 persistent=yes。78

发往 localhost 的通信不经过物理 NIC,所以在以物理适配器为对象的捕获里看不到。要用 Npcap 的环回适配器,或者 pktmon 的堆栈内采集。9

把能读出的事实和文件的处理分开考虑

即使 TLS 让内容不可见,连接的建立、TLS 握手的成败、RST、是哪一方不作声了,这些仍然查得出来。用 SSLKEYLOGFILE 解密则是仅限开发环境的手段。10

另一方面,捕获文件里装的就是通信内容本身。要以其中可能含有认证信息和个人信息为前提,把对象和时间范围压到最小,并把交到公司外部之前的筛选也纳入采集步骤。

图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 21 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle

2. 捕获的三种工具与分工

选择的标准是“现场能装什么”和“除了数据包还想留下什么”。先来比较这三种工具的角色。

  pktmon netsh trace Wireshark
获取方式 Windows 10 / Windows Server 2019 以后随系统内置4 长期以来随 Windows 内置(在 pktmon 出现之前的系统上也能用) 需要另行安装
主要角色 数据包采集、丢弃检测、计数器 数据包采集 + Windows 组件的 ETW 事件采集 分析采集到的数据(主力)
输出格式 ETL(用 etl2pcap 转换成 pcapng)1 ETL + .cab(用 etl2pcapng 转换成 pcapng)82 pcapng
独有的长处 能看出堆栈内的丢弃位置和丢弃原因5 按场景捆绑提供程序,跨越重启采集7 显示过滤器、TCP 分析、统计、GUI
权限 管理员权限 管理员权限 采集需要管理员级别(只做分析则不需要)

把角色分成 pktmon 和 netsh trace 负责“采”,Wireshark 负责“读”,思路会更清楚。Wireshark 本身也有采集功能,但在装不了它的现场用不上。

把自带工具的 ETL 转成文本来读也是可行的。不过,比起没有显示过滤器和 TCP 分析、只靠肉眼扫,转换成 pcapng 再用 Wireshark 分析更容易把调查推进下去。

采集用自带工具,阅读用 Wireshark展示在现场用 pktmon 或 netsh trace 采集 ETL,用各自的转换工具转成 pcapng,再在手边的 Wireshark 上分析的分工pktmon etl2pcapetl2pcapngpktmon(自带)ETL 文件netsh trace(自带)ETL + .cabpcapng在手边的 Wireshark 上分析

图2:现场用自带工具采集 ETL,转换成 pcapng 后在手边的 Wireshark 上阅读。

Microsoft 的丢包调查指南也是同样的结构,给出的顺序是:先用 pktmon 采集并定位原因,如果不够就进到 netsh trace start scenario=InternetClient 这类组件级别的跟踪,协议的行为则用 Wireshark 分析。3

另外,要读懂数据包里映出了什么,前提是能在脑中勾勒出 Ethernet、IP、TCP、应用数据这几层的叠加关系,有这个印象理解会快很多。分层的解剖在“把 OSI 参考模型彻底看懂”里做了图解。

3. pktmon 实务——过滤器→开始→停止→转换

采集的基本流程是注册过滤器→开始→停止→转换这 4 个步骤。结束后还要把过滤器清理掉。下面的命令都在管理员权限的终端里执行。

开始之前,请先确认已有的过滤器以及结束后的清理方式。最后那条 pktmon filter remove 不是按名称删除的操作,而是把已注册的过滤器全部删掉。在与其他调查共用的环境里,要先用 pktmon filter list 确认。

:: 1. 先注册过滤器缩小对象范围(目标服务器 192.168.10.20 的 TCP 8443)
pktmon filter add App8443 -i 192.168.10.20 -t tcp -p 8443
pktmon filter list

:: 2. 开始采集。记录整个数据包,用 1GB 的环形缓冲区覆盖写入
pktmon start --capture --pkt-size 0 --file-name C:\temp\app-timeout.etl --file-size 1024 --log-mode circular

:: 3. 让现象复现。等待期间可以用计数器确认流量和丢弃
pktmon counters --drop-reason

:: 4. 停止,并转换成 Wireshark 用的 pcapng
pktmon stop
pktmon etl2pcap C:\temp\app-timeout.etl --out C:\temp\app-timeout.pcapng

:: 5. 清理注册过的过滤器(过滤器在显式删除之前一直留着)。
::    注意: filter remove 不能指定名称,会把已注册的过滤器“全部”删除。
::    在还留着其他调查的过滤器的环境里,先用 pktmon filter list 确认
pktmon filter remove
pktmon 的基本步骤先用注册过滤器缩小对象范围再开始采集,让现象复现后停止,用 etl2pcap 转换成 pcapng,最后删除注册过的过滤器的流程1. 用 filter add 缩小对象范围2. 用 start --capture 开始采集3. 让现象复现用 counters 确认流量和丢弃4. 用 stop 停止用 etl2pcap 转换成 pcapng5. 用 filter remove 清理

图3:pktmon 从注册过滤器开始,采集、停止、转换之后还要显式清理过滤器。

执行命令之前先定好下面 4 点,可以减少返工重采。

采集前要确认的事项

缩小对象范围:多个过滤器是 OR 条件

过滤器要在开始采集之前注册。Microsoft 的文档也认为采集全部流量噪声太多,强烈建议在开始前应用过滤器。过滤器可以按 IP 地址、端口、MAC 地址、协议、VLAN ID 等指定,最多能注册 32 个。多个过滤器之间是“命中任意一个就记录”的 OR 条件。4

缩小方向:源和目的不作区分

pktmon 的过滤器不区分源和目的。-i 192.168.10.20 的意思是“以这个地址为源或为目的的数据包”。方向上的筛选,放到转换之后用 Wireshark 的显示过滤器来做。4

定好记录范围:只要头部,还是整个数据包

默认的数据包大小是 128 字节。只解析头部的话这就够了,但要读到应用数据,就用 --pkt-size 0 记录整个数据包。6

定好容量:环形缓冲区与实时显示

日志默认是 circular(环形缓冲区)模式,默认大小 512MB。除了用 --file-size 改上限,还可以用 --log-mode real-time 在屏幕上实时显示,这时不会生成日志文件。先用实时显示确认“想抓的通信确实看得到”,再布置正式采集,可以避免扑空。6

pktmon 过滤器的生效方式展示注册的多个过滤器按命中任意一个就记录的 OR 条件工作,指定的地址不区分源和目的,因此方向上的筛选要在转换之后用 Wireshark 的显示过滤器来做过滤器 1命中任意一个就记录过滤器 2过滤器 3(最多 32 个)记入采集日志(OR 条件)源和目的不作区分方向在转换之后用 Wireshark 筛选

图4:多个过滤器按 OR 条件工作,是源还是目的这个方向问题,转换之后用 Wireshark 筛选。

3.1. pktmon 独有的长处——能看出在哪里被丢掉

与 Wireshark 不同,pktmon 的独有价值在于不是在 NIC 这一个点上,而是在网络堆栈内的多个位置捕捉数据包,能报告数据包被丢弃的位置和原因。由于能看出数据包到达了哪个组件、又在哪里消失,从“MTU 不一致”“VLAN 过滤”这类丢弃原因出发,不必逐一穷举就能找到原因。5

pktmon 在堆栈内的多个位置捕捉展示 pktmon 不是在 NIC 这一个点而是在网络堆栈内的多个位置捕捉数据包,因此能带上原因报告数据包到达了哪个组件、又在哪里被丢弃数据包在位置 1 捕捉在位置 2 捕捉在位置 3 丢弃报告丢弃位置和丢弃原因例 MTU 不一致或 VLAN 过滤

图5:因为在堆栈内的多个位置捕捉,所以能带上原因看出送到了哪里、又在哪里被丢掉。

先看计数器,必要时再用文本日志确认

  • 用 pktmon list 可以查看会被监视的网络组件(NIC、协议栈、筛选器驱动程序等)的清单和 ID。
  • 用 pktmon counters --drop-reason 可以列出各组件的通过/丢弃计数器和最近的丢弃原因。作为解析日志之前的初步定位很方便。11
  • 用 pktmon etl2txt 转成文本后,被丢弃的数据包会带着 drop 和 dropReason(丢弃原因)一起输出。4

“是不是在送到应用之前就被操作系统的某个环节丢掉了”这种怀疑,光盯着 Wireshark 是定不下来的。比如因为入站规则不完善而被防火墙丢掉的情形(“Windows 防火墙与业务应用”),排查时这个功能就管用。

交给 Wireshark 之前,先缩小捕捉位置

pktmon 会在堆栈内的多个位置记录同一个数据包。原样转换成 pcapng,同一个数据包可能会重复出现。因为 pcapng 不会继承“在哪个组件捕捉到的”这一信息。

如果目的是用 Wireshark 阅读,就用 pktmon etl2pcap 的 --component-id 限定位置再转换。也可以用 --drop-only 把丢弃的数据包单独放到另一个文件里。1

转换成 pcapng 后同一个数据包重复出现的原因展示 pktmon 会在堆栈内的多个位置记录同一个数据包,而 pcapng 不会继承在哪个组件捕捉到的信息,因此可能重复出现,所以惯常做法是用 component-id 限定位置,或者用 drop-only 把丢弃的数据包单独转换到另一个文件同一个数据包在多个位置被记录原样转换成 pcapng捕捉位置的信息不被继承同一个数据包重复出现用 --component-id 限定位置用 --drop-only 放到另一个文件

图6:捕捉位置的信息不会被 pcapng 继承,所以惯常做法是先限定位置再转换。

4. netsh trace 实务——场景与 ETL,跨越重启的采集

netsh trace 是比 pktmon 更早就装在 Windows 上的跟踪采集机制。它的特点是能以“场景”为单位,把与该问题相关的一整套 ETW 提供程序一次性启用。8

:: 查看可用场景的清单,以及场景中包含哪些提供程序
netsh trace show scenarios
netsh trace show scenario netconnection

:: 开始采集。含数据包捕获,1GB 的循环缓冲区
netsh trace start scenario=netconnection capture=yes tracefile=C:\temp\nettrace.etl maxSize=1024 filemode=circular

:: 让现象复现之后再停止(合并处理要花一点时间)
netsh trace stop

用 netsh trace 时要定的采集条件

要连数据包一起留下就加 capture=yes

加上 capture=yes 就会启用数据包捕获,可以用 ipv4.address=192.168.10.20 这样的捕获过滤器缩小对象范围。过滤器的清单用 netsh trace show capturefilterHelp 查看。8

除了 ETL,还会留下 .cab 里的环境信息

停止后除了 ETL 文件,还会生成 .cab 文件。.cab 里包含适配器配置、系统内部版本等系统信息,可以顺带完成环境信息的收集。8

开始前先确认已有的会话

跟踪会话同时只能运行一个。开始另一次采集之前,先用 netsh trace show status 确认有没有一直跑着没停的会话。8

重启刚结束时发生的现象要用 persistent=yes

加上 persistent=yes,会话就能跨越重启保持下去。“只有重启刚结束的一瞬间通信失败”“启动时的服务连接失败”这类手动来不及开始的现象,采集起来正是 netsh trace 的独门领域。7

netsh trace 的场景采集展示指定场景开始后会把一整套 ETW 提供程序捆在一起启用,加上 capture=yes 还会采集数据包,停止后会生成 ETL 文件和 .cab 文件的流程capture=yes指定场景并开始启用一整套提供程序同时采集数据包让现象复现用 stop 停止ETL 文件.cab(系统信息)

图7:用场景开始会把一整套提供程序捆在一起启用,停止时生成 ETL 和 .cab。

4.1. 把 ETL 变成 Wireshark 能读的形式——etl2pcapng

netsh trace 的 ETL 原样是打不开的。用 Microsoft 在 GitHub 上公开的开源工具 etl2pcapng,可以把 netsh trace start capture=yes 采到的 ETL 中的数据包转换成 pcapng。2

etl2pcapng.exe C:\temp\nettrace.etl C:\temp\nettrace.pcapng

etl2pcapng 在转换时会把与数据包相关的进程 ID 作为数据包注释写出来。能在 Wireshark 上确认“这是哪个进程的通信”,在同一台服务器上有多个应用通信的环境里,排查时很有帮助。2

数据包和 Windows 内部事件,读法不一样

另外,ETW 事件那一侧(场景提供程序记录的 Windows 内部事件)不会被转换成 pcapng。要连事件一起读的话,用 netsh trace convert input=C:\temp\nettrace.etl 转成文本等格式,或者用 Windows Performance Analyzer 之类的工具打开。73

netsh trace 的 ETL 读法分成两路展示 ETL 里的数据包用 etl2pcapng 转成 pcapng 后用 Wireshark 阅读,而 ETW 事件不会转换成 pcapng,要用 netsh trace convert 或 Windows Performance Analyzer 来读etl2pcapngnetsh trace 的 ETL数据包ETW 事件转换成 pcapng用 Wireshark 阅读进程 ID 留在注释里不会转换成 pcapng用 convert 或 WPA 阅读

图8:ETL 里数据包转成 pcapng 来读,ETW 事件则用另外的手段来读。

5. Wireshark 阅读入门——显示过滤器与 TCP 分析

分析按缩小对象→确认 TCP 的形态→必要时通看整段对话的顺序推进。先打开 pcapng,用显示过滤器削掉噪声。1213

用显示过滤器缩小阅读对象

显示过滤器 含义
ip.addr == 192.168.10.20 以这个 IP 为源或为目的的数据包
tcp.port == 8443 牵涉这个 TCP 端口的数据包
dns 只看 DNS 的查询和响应
tcp.flags.syn == 1 && tcp.flags.ack == 0 只看发起连接的 SYN
tcp.flags.reset == 1 只看 RST(强制断开)
tcp.analysis.retransmission Wireshark 判定为重传的数据包
tcp.analysis.zero_window 接收窗口为 0(接收方已经收不下的状态)
tcp.analysis.flags 检测到某种问题的全部数据包

tcp.analysis.* 是 Wireshark 跟踪 TCP 序列号后自动判定出来的分析标记。重传、重复 ACK、乱序、ZeroWindow 等都能被机械地挑出来,所以一上来先敲 tcp.analysis.flags,把“看着像有问题的地方”列一遍,是开始阅读时的惯常做法。13

把超时拆成 4 个确认点

用 tcp.analysis.flags 找到大致方向之后,按下面的顺序确认。尤其要注意,重传只是“没有收到 ACK”这一观测结果,重要的是不要仅凭单侧就断定丢的是去程还是回程。

1. 连接建立了吗:SYN、SYN/ACK、ACK

三次握手完成了吗。SYN→SYN/ACK→ACK 这三发齐了没有。如果反复发 SYN 却没有响应,那就是没送到对方,或者在中途被默默丢掉了(防火墙的典型情形)。

2. 是否被强制断开:RST 的时刻与源

RST 是从哪一边飞出来的。对 SYN 立刻回 RST,说明目标端口上没人在监听;连接建立之后才出现 RST,说明某一方强制断开了连接。RST 的源 IP 就是“是哪一方断开的”的直接证据。

3. ACK 有没有回来:重传是否持续

重传是不是一直在继续。同一个分段反复重传,是发送方没有收到确认应答(ACK)的信号。去程的数据丢了,还是回程的 ACK 丢了,仅凭单侧的捕获定不下来(正因如此,下一章的“两端都采”才有用)。重传和超时的深入讨论,在“TCP 重传导致工业相机通信中断的原因与排查”里有详细展开。

4. 接收方是不是堵住了:ZeroWindow

有没有出现 ZeroWindow。这是接收端应用没有从套接字读出数据、接收缓冲区被塞满的信号。它可以成为怀疑接收端应用设计(“TCP 中“发送单位=接收单位”的误区”)而非网络的依据。

超时调查中寻找形态的顺序按三次握手是否完成、有没有 RST 及其来源、重传是否持续、有没有 ZeroWindow 的顺序确认,从而圈定原因的流程否是是否是否是SYN 收到响应了吗?疑似没送到就被丢掉(防火墙的典型)有 RST 飞出来吗?RST 的源就是断开的一方重传还在继续吗?这是 ACK 没有回来的信号出现 ZeroWindow 了吗?这是接收端应用没有读取的信号

图9:按握手、RST、重传、ZeroWindow 的顺序找形态,就能圈定下一步要查的地方。

通信量大的时候,先用统计俯瞰再读

在逐个数据包读之前,先用统计找出目标对话和时间段,也是有效的做法。

功能 要看什么 下一步操作
[统计]→[对话(Conversations)] 哪一对 IP、哪一对端口,从什么时候到什么时候,说了多少 只过滤出目标对话
[统计]→[I/O 图表(I/O Graph)] 时间轴上的流量。诸如“从这个时刻起只有一个方向静默了”这样的变化 缩小要调查的时间段
右键点击对话→[追踪流]→[TCP 流] 这个连接上的往来 把明文往来通读一遍。TLS 下看不到内容时怎么办,见第 8 章
先用统计俯瞰再缩小到具体对话展示用 Conversations 列出哪些通信在什么时候说了多少以锁定目标对话,用 I/O 图表把握静默下来的时间段,再只过滤出目标对话并用 TCP 流通读的流程用统计俯瞰全局用 Conversations 列出对话用 I/O 图表查看流量只过滤出目标对话能看出静默开始的时刻用 TCP 流通读

图10:逐个数据包读之前先用统计俯瞰,缩小到目标对话再通读。

6. 环回通信的陷阱——发往 localhost 的通信不经过 NIC

想调查同一台 PC 内应用之间的通信——比如业务应用连到 localhost:8080 上的中间服务——结果卡在“Wireshark 里什么都不出现”,这是经典的陷阱。

原因很明确:发往 localhost(127.0.0.1)的通信不经过物理 NIC,而是在操作系统内部的环回路径上折返。在以物理适配器为对象的常规捕获里,它从一开始就不会出现。9

发往 localhost 的通信不出现在捕获里的原因展示发往 localhost 的通信不经过物理 NIC 而是在操作系统内部的环回路径上折返,因此不会出现在以物理适配器为对象的常规捕获里发往外部发往 localhost应用网络堆栈物理 NIC会出现在常规捕获里在操作系统内部折返不会出现在常规捕获里用 Npcap 环回或 pktmon 采集

图11:发往 localhost 的通信在 NIC 之前就折返了,所以物理适配器的捕获里从一开始就没有它。

让采集方法匹配环回路径

应对办法有两种。

  • 用 Wireshark 采集时:把 Npcap 提供的“Adapter for loopback traffic capture”选为捕获对象。Windows 版 Wireshark(3.0 以后)的安装程序里附带了 Npcap,所以装了 Wireshark 的环境不需要额外操作就能用。9
  • 用自带工具采集时:pktmon 不是在 NIC 外侧,而是在网络堆栈内部的多个位置采集5,所以也能用来观察环回通信。要做到万无一失,在布置正式的复现等待之前,先用 pktmon start -c -m real-time 的实时显示,在那个环境上确认目标环回通信确实看得见。

在地址的指定上,也有两处容易搞混

localhost 指的不一定是 127.0.0.1

“localhost”有可能被解析成 IPv6 的 ::1。这是一种常见情形:应用连的是 IPv6 的 ::1,而调查一方只盯着 127.0.0.1(IPv4),于是误判成“没有通信”。显示过滤器要像 ip.addr == 127.0.0.1 || ipv6.addr == ::1 这样两边都写上,或者在应用的连接目标配置里用地址明确指定。9

即使指定自己的真实 IP,也不一定经过物理 NIC

发往自己真实 IP 的通信,同样不会出现在线路上。在同一台 PC 上从 192.168.10.5 连向 192.168.10.5 时,即便目的地是真实 IP,也是在操作系统内部折返。请记住,“因为指定的是真实 IP,所以应该经过 NIC”并不成立。

localhost 被解析成 IPv6 的混淆展示应用的 localhost 有可能被解析成 IPv6 的 ::1 并据此连接,而调查一方只看 127.0.0.1 就会误判成没有通信,因此要么两个地址都设过滤器,要么用地址明确指定连接目标来确认应用连接到 localhost实际解析到 ::1(IPv6)调查一方只看 127.0.0.1画面上什么都不出现对两个地址都设过滤器用地址明确指定连接目标

图12:注意 localhost 被解析成 ::1、只看 127.0.0.1 就误判成“没有通信”这种混淆。

7. 在哪里采集——单侧、两端,还是时间同步

单侧能得到的,是从那个采集点看到的事实。是先看全局,还是要确认通信是在去程还是回程消失的,采集位置按这个来选。

采集位置 能知道什么 适合的情况
仅客户端 自己发了什么,回来了什么 先掌握全局。碰不到服务器的情况
仅服务器端 请求有没有到达,有没有返回响应 客户端很多、无法锁定是哪一台的情况
两端同时 数据包在路径的哪一段消失,是哪一方不作声了 想确定责任边界的情况

即使在客户端侧看到重传一直在继续,仅凭单侧也区分不了下面两种情况。

  • 发出去的数据包在到达服务器之前就消失了。
  • 数据包到达了服务器,但响应在回程上消失了。

两端都采集再比对,就能确定“客户端发了、服务器没收到”这样的结论,也就知道是哪一方不作声了。在需要确定责任边界(应用、操作系统、网络设备、对方)的场合,一开始就安排两端同时采集。

单侧采集与两端采集各自能知道什么展示单侧的捕获无法区分是去程的数据包消失了还是回程的响应消失了,而两端都采集再比对就能确定是哪一方不作声了仅在单侧采集只有从自己位置看到的事实区分不了是去程消失还是回程消失两端同时采集比对确定是哪一方不作声了前提是两台机器的时间同步

图13:单侧只能知道看到的事实,两端比对才第一次确定责任边界。

7.1. 比对的前提是时间同步

要把两端的捕获比对起来,两台机器的时钟必须对齐。开始采集之前,先确认并记录时间上的偏差。

:: 确认时间同步的状态(同步源、最后一次同步时刻)
w32tm /query /status

:: 实测与对方服务器的时间差(5 个采样)
w32tm /stripchart /computer:sv-app01 /dataonly /samples:5

w32tm /stripchart 是显示自己与对方计算机之间时间偏移量的命令,比对时它就是“服务器端的时间快了 0.8 秒”这类校正的依据。14 在偏差很大的环境里,先把时间同步修好再采集,结果反而更快。

比对之前确认时间差的步骤展示用 w32tm 确认自己的时间同步状态,用 stripchart 实测与对方服务器的时间差并记录下来,在比对时把这个偏差用作校正依据的流程,以及偏差很大的环境要先把时间同步修好再采集用 query 确认同步状态用 stripchart 实测时间差把偏差记录下来比对时作为校正的依据偏差大就先把同步修好

图14:采集之前实测并记录时间差,作为比对时校正的依据。

7.2. “不知道什么时候会发生”就用环形缓冲区

复现条件不明的现象,基本做法是用环形缓冲区一直采着,等发生了再停。

  • pktmon:默认就是 circular 模式。用 --file-size 指定上限(MB),旧的数据包会被覆盖。6
  • netsh trace:像 maxSize=1024 filemode=circular 这样指定。7
  • Wireshark:在[捕获]→[选项]→[输出]里可以配置“多个文件 + 环形缓冲区”。它按文件大小或时间切换,只保留最新的 N 个,所以能在给磁盘用量设上限的同时长时间运行。15

不只是容量,连发生之后怎么停也要定好

不管用哪一种,都请和现场负责人约定好这样的做法:现象发生后,先记下发生时刻,再停止采集。环形缓冲区越等越会抹掉过去,从发生到停止的步骤一长,关键的那一段就被覆盖掉了。

用环形缓冲区守株待兔的做法展示复现条件不明的现象用环形缓冲区一直采着等待,现象发生后先记下发生时刻再迅速停止的做法,以及停止一晚旧的数据包就会被覆盖、关键区段随之消失用环形缓冲区开始采集一直采着等待现象发生记下发生时刻迅速停止从旧的数据包开始覆盖停晚了关键区段就没了

图15:环形缓冲区越等过去越会被抹掉,所以记下发生时刻后要迅速停止。

8. TLS 下看不到内容的问题——看不到也能知道的事

解密之前,先确认通信的骨架

如今的业务通信大多是 TLS(HTTPS)。人们容易觉得“既然加密了,抓包不也白抓”,但超时调查里想知道的大部分内容,在加密状态下照样能知道。

  • TCP 连接有没有建立(三次握手)
  • TLS 握手进行到了哪一步——对 ClientHello 有没有返回 ServerHello,握手途中是否被 RST 或告警切断
  • ClientHello 里携带的目标主机名(SNI),以及协商出来的 TLS 版本
  • 建立之后是哪一方停止了发送。无响应的位置、重传、RST,还是正常关闭(FIN)

也就是说,排查“连不上”“中途断开”“不返回响应”,几乎不需要解密内容。加密丢掉的是“说了什么”,而“谁在什么时候不作声了”仍然留着。

TLS 的捕获里看得到和看不到的东西展示加密后看不到的只有应用数据的内容,而 TCP 连接的建立、TLS 握手的成败、SNI 和 TLS 版本、RST 以及是哪一方不作声了,在加密状态下依然能知道TLS 通信的捕获看得到的看不到的TCP 连接的建立TLS 成败与 SNIRST 与哪一方不作声应用数据的内容

图16:加密丢掉的只是内容,通信的骨架在 TLS 下照样读得出来。

只有确实需要内容时,才去确认能不能解密

即便如此还是需要内容时,Wireshark 有一套机制:用 SSLKEYLOGFILE 环境变量写出的会话密钥来解密 TLS。不过支持它的只有 Firefox、Chrome、Chromium 系 Edge 等浏览器和 OpenSSL 系库等一部分实现,Windows 自带的 SChannel(使用 WinHTTP 或 WinINET 的应用)并不支持这套机制。10 由于会话密钥会被写进文件,也就意味着拿到那个文件的人可以把通信全部解密,因此应当把它定位为不用于生产环境、只用于开发环境复现和调试的手段。

SSLKEYLOGFILE 解密的机制与限制展示用 SSLKEYLOGFILE 写出的会话密钥可以在 Wireshark 里解密 TLS,但支持的只有 Firefox 和 Chrome 系等一部分实现,SChannel 并不支持,而且拿到密钥文件的人可以解密通信,因此是仅限开发环境的手段设置 SSLKEYLOGFILE把会话密钥写出到文件在 Wireshark 里解密阅读持有密钥的人能全部解密定位为仅限开发环境只有一部分 TLS 实现支持SChannel 不支持

图17:写出会话密钥就能解密,但支持的实现有限,而且密钥本身的性质决定了它只适合开发环境。

另外,经由企业内部代理的通信,捕获里映出的目标会变成代理服务器,TLS 是在 CONNECT 隧道里流动的。至于应用究竟走向哪个代理这个更靠前的问题,在同日发布的姊妹文章“企业内部代理与 Windows 应用——理清 WinINET、WinHTTP、.NET 的代理解析”里做了梳理。

9. 与应用日志的比对——把时刻排到同一根轴上

光靠捕获本身就能得出结论的情况,其实并不多。实务上的决定性一步,是把应用日志的一行和数据包的一个来回,摆到同一条时间轴上。

把日志的一行换成数据包上的观测事实

先从出现异常的时刻,去找通信开始的那一段。

步骤 1:从异常时刻和超时值找出开始时刻

从应用日志锁定现象的时刻(例:10:23:41 出现超时异常)。如果超时值是 30 秒,那么开始时刻应该在 10:23:11 前后。

步骤 2:把 Wireshark 切成日期时间显示,缩小到对应区间

把 Wireshark 的时间显示切换到[视图]→[时间显示格式]→[日期和时间],再用显示过滤器缩小到对应区间(也可以像 frame.time >= "2026-08-20 10:23:00" && frame.time <= "2026-08-20 10:24:00" 这样按时刻筛选)。

步骤 3:确认握手、RST、重传、ZeroWindow

在那一段里,按第 5 章的顺序(握手→RST→重传→ZeroWindow)确认。只要能比对到“在日志的超时时刻之前 30 秒发出了 SYN,之后只有 SYN 的重传”,日志里那句“超时”就被换成了“在这个采集点上一个响应都没有回来”这一观测事实(至于是 SYN 没送到对方,还是响应的 SYN/ACK 在回程上丢了,仅凭这个采集点定不下来。想要定下来就和服务器端的采集比对)。

步骤 4:校正时间差和时区

捕获的时刻与日志的时刻之间的偏差(7.1 节测出的时间差、日志的时区标注)一定要校正。比对时哪怕差几秒,都可能把另一段通信当成凶手。

应用日志与数据包的比对步骤展示从应用日志锁定现象的时刻,由超时值倒推开始时刻,用 Wireshark 缩小到对应区间并按顺序确认形态,再校正时间偏差把两者排到同一条时间轴上的步骤1. 用日志锁定现象的时刻由超时值倒推开始时刻2. 用显示过滤器缩小到对应区间3. 按第 5 章的顺序确认形态4. 校正时间偏差日志里那一句变成观测事实

图18:从日志的时刻缩小区间,确认形态,校正时间差后排到同一根轴上。

交给第三方之前,只取出必要的对话

把调查结果交给第三方(厂商、线路运营商、客户的网络负责人)时,先用过滤器削掉噪声再交出去,既是礼貌,也是安全措施。在 Wireshark 里用显示过滤器只留下目标对话,再用[文件]→[导出特定分组]保存“仅显示的分组”,就能做出只含必要范围的小体积 pcapng。

从采集之前就定好机密信息的保管与删除

捕获文件里装的就是通信内容本身。其中可能含有明文协议的认证信息、HTTP 的 Cookie 和 API 密钥、邮件和单据的内容、个人信息。下面 3 点请与采集步骤一起定好。

  • 必要最小限度的采集:用采集前过滤器(第 3 章、第 4 章)缩小对象,时间范围也压到最小。不要在客户环境里“先全都采下来再说”
  • 交出去之前的筛选:只导出目标对话,不要把无关第三方的通信包含进去。仍然留有机密部分时,与接收方商定脱敏或改用其他途径
  • 保管与删除:定好采集文件的存放位置、期限和删除方式,调查结束后就清掉
交出捕获文件之前的三项约定展示因为捕获里装的就是通信内容本身,所以要用采集前过滤器和时间范围压到必要最小限度,交出去之前只提取目标对话而不包含无关通信,并定好存放位置和期限、调查结束后删除这三点,与采集步骤一起定下来捕获里装着通信内容采集压到必要最小限度交出去之前只提取目标定好保管期限并删除用显示过滤器筛选后导出

图19:最小限度的采集、交出去之前的筛选、保管与删除这三点,要与采集步骤一起定好。

10. 总结

  • 应用日志里“超时”的下一层,有着实际流经线路的数据包这一事实。是 SYN 没有响应,是被 RST 断开,是重传一直在继续,还是 ZeroWindow,下一步要查的地方随之不同。
  • 即使现场装不了 Wireshark,也能用 Windows 自带的 pktmon 和 netsh trace 采集。采集用自带工具,阅读用手边的 Wireshark,这样的分工是基本做法。
  • pktmon 是注册过滤器→pktmon start --capture→pktmon stop→pktmon etl2pcap 这 4 个步骤。默认会被截断到 128 字节,所以要读到内容别忘了 --pkt-size 0。能看出丢弃位置和原因,是只有 pktmon 才有的长处。
  • netsh trace 能以场景把 ETW 提供程序捆在一起采集,用 persistent=yes 跨越重启。ETL 用 etl2pcapng 转换成 pcapng 再读。
  • 在 Wireshark 里从 tcp.analysis.flags 开始读,按握手、RST、重传、ZeroWindow 的顺序找形态。先用 Conversations 和 I/O 图表俯瞰再缩小,速度更快。
  • 发往 localhost 的通信不经过 NIC,所以常规手段采不到。要用 Npcap 的环回适配器,或者 pktmon 的堆栈内采集。
  • 两端都采集再比对,就能确定“是哪一方不作声了”。其前提是时间同步(w32tm)。复现条件不明的现象用环形缓冲区守株待兔。
  • 即使是 TLS,通信的骨架也看得见。解密(SSLKEYLOGFILE)要定位为仅限开发环境的手段,捕获文件本身也要当作机密,把最小采集、筛选、删除纳入日常流程。

数据包捕获常被当成“网络专家的工具”,但实际上它是要与应用日志比对之后才产生意义的、应用侧的调查工具。下次调查因为“超时”这一句话而停住时,请去看它的下一层。

相关文章

相关咨询领域

合同会社小村软件承接“业务应用的通信时不时失败但查不出原因”“想排查只在客户环境里出现的连接错误”这类以通信为起点的故障调查。从数据包捕获的采集设计(在哪里采、采什么、采多少),到用 Wireshark 分析、与应用日志比对,再到应用侧的修改,一条线接到底。

参考链接

  1. Microsoft Learn, pktmon etl2pcap。关于把 pktmon 的 ETL 日志转换成 Wireshark 等可分析的 pcapng 格式,以及 pcapng 格式会丢失丢弃信息和堆栈内捕捉位置的信息,因此应先用 –drop-only 或 –component-id 缩小范围再转换。 ↩ ↩2 ↩3

  2. GitHub, microsoft/etl2pcapng。关于它是把 netsh trace start capture=yes 等采集到的 ETL 文件中的数据包转换成 pcapng 格式的 Microsoft 开源工具,会保留接口信息,并把进程 ID 作为数据包注释写出。 ↩ ↩2 ↩3 ↩4

  3. Microsoft Learn, Diagnose packet loss。关于丢包调查中先用 pktmon 采集跟踪、确认本地的丢弃原因和统计,并与 Wireshark 的协议级分析相结合,若仍不充分再进到 netsh trace 的场景所提供的组件级跟踪这一官方调查步骤。 ↩ ↩2 ↩3

  4. Microsoft Learn, Pktmon command formatting。关于 pktmon.exe 在 Windows 10 和 Windows Server 2019(版本 1809)以后可用,注册过滤器→开始→复现→确认计数器→停止并转换的快速上手步骤,过滤器最多 32 个且为 OR 条件、不区分源和目的,以及文本输出中被丢弃的数据包会带上 dropReason。 ↩ ↩2 ↩3 ↩4 ↩5

  5. Microsoft Learn, Packet Monitor (Pktmon)。关于 Packet Monitor 是 Windows 自带的跨组件诊断工具,会在网络堆栈内的多个位置捕捉数据包并可视化数据包的路径,对支持的组件会带上丢弃原因(MTU Mismatch、Filtered VLAN 等)报告丢弃情况,以及提供按位置统计的数据包计数器。 ↩ ↩2 ↩3 ↩4

  6. Microsoft Learn, pktmon start。关于用 –capture 开始采集,–pkt-size 默认为 128 字节、指定 0 可记录整个数据包,–file-name 与 –file-size(默认 512MB),以及 –log-mode 的各个模式(circular、multi-file、real-time、memory)和默认为 circular。 ↩ ↩2 ↩3 ↩4

  7. Microsoft Learn, netsh trace。关于 netsh trace start 的 scenario、capture、tracefile、maxSize、fileMode(circular 作为环形缓冲区工作)、persistent(跨越重启保持会话)等参数,以及用 netsh trace convert 把 ETL 转换成文本等格式。 ↩ ↩2 ↩3 ↩4 ↩5

  8. Microsoft Learn, Using Netsh to manage traces。关于场景是为故障排除预先定义好的提供程序集合,用 netsh trace show scenarios / show scenario 查看,跟踪会话同时只能运行一个,capture=yes 时的数据包过滤器(ipv4.address 等),以及停止时会生成 ETL 和包含系统信息的 .cab。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  9. Wireshark Wiki, CaptureSetup/Loopback。关于在 Windows 上以物理 NIC 为对象的常规捕获采集不到发往 127.0.0.1 的环回通信,用 Npcap 的“Adapter for loopback traffic capture”可以采集环回通信,以及 Wireshark 3.0 以后的 Windows 安装程序附带 Npcap。 ↩ ↩2 ↩3 ↩4

  10. Wireshark Wiki, TLS。关于用 SSLKEYLOGFILE 环境变量写出的会话密钥可以在 Wireshark 里解密 TLS,支持的是 Firefox、Chrome、Chromium 系 Edge、OpenSSL 系库等,而 Microsoft 的 SChannel 不支持这套机制。 ↩ ↩2

  11. Microsoft Learn, pktmon counters。关于 pktmon counters 显示各被监视组件的通过与丢弃计数器,–drop-reason 可以显示各丢弃计数器最近的丢弃原因,以及 –live 的实时更新。 ↩

  12. Wireshark, Building Display Filter Expressions (Wireshark User’s Guide)。关于显示过滤器的语法,ip.addr、tcp.port 等字段的指定方式、比较运算符,以及用 and/or/not 组合。 ↩

  13. Wireshark, TCP Analysis (Wireshark User’s Guide)。关于 Wireshark 的 TCP 分析标记(tcp.analysis.retransmission、tcp.analysis.duplicate_ack、tcp.analysis.out_of_order、tcp.analysis.zero_window 等)的清单,以及各自的判定条件。 ↩ ↩2

  14. Microsoft Learn, Windows Time service tools and settings。关于 w32tm 是用于 W32Time 的配置、监视和故障排除的推荐命令行工具,以及 w32tm /stripchart 显示自己与对方计算机之间的时间偏移量(/dataonly、/samples 等选项)。 ↩

  15. Wireshark, Capture files and file modes (Wireshark User’s Guide)。关于捕获文件的输出模式(单个文件、多个文件、环形缓冲区),以及环形缓冲区只保留最新的数据从而能给磁盘用量设上限。 ↩

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

常见问题

汇总了咨询这一主题时常见的问题。

在装不了 Wireshark 的客户服务器上,要怎么采集数据包?
用 Windows 自带的 pktmon 或 netsh trace,不额外安装软件也能采集。用 pktmon 时,在管理员权限的终端里注册过滤器,用 pktmon start --capture 开始采集,用 pktmon stop 停止。采到的 ETL 文件可以用 pktmon etl2pcap 转换成 pcapng 格式,分析则带回本公司,在自己手边的 Wireshark 上做。“采集用自带工具,阅读用 Wireshark”这样的分工,是有安装限制的现场的基本做法。
pktmon 和 netsh trace 该用哪一个?
只要操作系统支持 pktmon(Windows 10 / Windows Server 2019 以后),建议先用 pktmon。因为它命令简单,还能确认数据包是在网络堆栈的哪个组件被丢弃的(丢弃原因),pcapng 转换也由它自己就能完成。netsh trace 占优势的场合是:在没有 pktmon 的旧系统上采集、想以场景的形式把 Windows 组件的 ETW 事件一并采集、想用 persistent=yes 跨越重启继续采集。Microsoft 的故障排除资料给出的顺序也是先 pktmon,不够再用 netsh trace。
发往 localhost(127.0.0.1)的通信为什么在 Wireshark 里显示不出来?
因为发往 localhost 的通信不经过物理 NIC,而是在操作系统内部的环回路径上折返。以物理适配器为对象的常规捕获里,它从一开始就不会出现。在 Wireshark 中选择 Npcap 提供的“Adapter for loopback traffic capture”,就能采集环回通信。pktmon 是在网络堆栈内部采集的,所以也能用来观察环回通信。另外还常见一种混淆:“localhost”被解析成 IPv6 的 ::1,而你以为在看 127.0.0.1 的画面上什么都没有出现——请明确指定地址后再确认。
HTTPS(TLS)通信的内容,用数据包捕获能看到吗?
应用数据的内容是加密的,看不到。不过 TCP 连接的建立与断开、TLS 握手的成败、被 RST 断开、是哪一方停止了响应,这些“通信的骨架”即使加密也看得出来,因此超时调查的大半工作可以在 TLS 保持加密的状态下推进。确实需要看内容时,有通过 SSLKEYLOGFILE 解密这一手段,但支持它的只有 Firefox、Chrome 系等一部分 TLS 实现,Windows 自带的 SChannel 并不支持。由于这是把密钥信息写出到文件的机制,即使要用,也请视为仅限开发环境。
把采集到的捕获文件发给公司外部的支持窗口,没问题吗?
原样发出去很危险。捕获文件里装着通信内容本身,可能含有明文协议的认证信息、Cookie、API 密钥和个人信息。首先要在采集阶段用过滤器和时间范围压到必要的最小限度,交出去之前再用 Wireshark 的显示过滤器只提取目标通信并导出。即便如此仍然留下的内容,应当与接收方商量,确定机密部分的处理方式(脱敏、改用其他途径提供)之后再交付。采集文件的保管期限和删除,也建议事先定好。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表