从微软自家工具切入抓包这件事,很多人第一反应是“干嘛不直接用 Wireshark”。这个想法本身没错,但如果你日常主要泡在 Windows 环境里排查问题,Microsoft Network Monitor(以下简称 Netmon)这套老工具反而有它不可替代的顺手之处。特别是它的抓包筛选器(Capture Filter)和显示筛选器(Display Filter)思路非常清晰,配合 DNS、IP、ICMP 这三类最常见流量的过滤,能在几分钟内从一堆乱糟糟的报文里把目标找出来。
这篇文章不打算铺开讲全功能的界面操作,而是围绕“筛选器”这个核心,结合我多年用 Netmon 排障的经验,把 Capture Filter 和 Display Filter 的差异、语法、实战套路、常见坑一次讲透。适合系统管理员、网络运维,以及需要自己抓包分析协议栈的开发人员参考。无论你是第一次接触抓包,还是已经用过 Wireshark 想换个工具,这篇文章都能给你一套能直接抄的过滤组合。
1. 抓包前先搞清楚:Capture Filter 和 Display Filter 到底差在哪
1.1 两类筛选器的本质区别
很多新手拿着抓包工具就开抓,抓到一段流量后直接在界面上筛选,以为“筛选”就是搜索框。但实际上,Netmon 提供了两个不同层面的筛选器,它们生效的时机完全不同,搞混了会在排障时浪费大量时间。
Capture Filter(捕获筛选器)在数据包进入抓包引擎的那一刻就开始生效。它决定哪些包被写入 .cap 文件或内存缓存里,哪些包压根不会被记录。这个动作发生在报文到达网卡驱动层之后、协议解析之前。换句话说,如果你的捕获筛选器写明“只抓 ICMP 报文”,那么所有 TCP、UDP、ARP 报文根本不会进入 Netmon 的捕获缓冲区,你后续在显示区域里也看不到它们。它的价值是“源头节流”,直接控制采集范围。
Display Filter(显示筛选器)则完全不同。它是在数据包已经被完整捕获、完成协议解析之后,作用于已捕获数据集的“视图过滤”。它不会删除、修改或影响已经抓下来的数据,只是把不符合条件的帧暂时隐藏。你可以随时切换条件、随时撤销、反复对比。抓下来的原始数据一直在,显示过滤只是改变了你看它的角度。
用一个生活化例子来记忆:Capture Filter 是单位门口的保安,进门的时候查证件,不符合条件的连门都进不了;Display Filter 是屋里的秘书,只要你已经进了屋,秘书可以按你的需要把不同的资料从抽屉里挑出来摆在你面前,资料本身没有消失。
这个区别直接决定了你在什么时候用哪一种。如果目标是“我只关心 DNS 流量,其他都不要”,用 Capture Filter 可以大幅降低磁盘写入和解析压力。但如果你担心漏掉某些“意外”报文,希望事后还能从完整流量里重新分析,那 Capture Filter 就要慎用,宁可让文件大一点,也要靠 Display Filter 兜底。
1.2 为什么 Netmon 仍然值得用
先交代一下背景,Microsoft Network Monitor 其实已经停止官方更新,最新可用版本是 3.4,发布于 2010 年。按说这类停更工具早该被历史淘汰,可它在某些场景里依然有很硬的竞争力。
最核心的一点是它运行在 Windows 原生环境,不依赖 WinPcap/Npcap 这类第三方驱动,安装起来非常省事。很多公司内网安全策略比较严格,不允许随便装驱动级工具,Netmon 反而容易过审。其次,它对微软自家协议做了深度解析,比如 SMB、RPC、LDAP、Kerberos、DCOM,这些协议 Wireshark 虽然也能解析,但 Netmon 的帧头布局和字段命名更贴近微软的代码习惯,做 Windows 域环境或 Exchange 环境排障时,对照事件 ID 和协议字段几乎可以无缝衔接。
再加上它的筛选器语法设计得相当直观,Capture Filter 和 Display Filter 使用的字段名高度统一,学会了其中一个,另一个基本是零成本迁移。这也是我今天愿意花篇幅专门讲筛选器的原因,真正用熟之后,它比在 Wireshark 里拼 display filter 字符串更顺手。
2. Capture Filter 实战:从源头把流量“瘦身”
2.1 Capture Filter 语法基础
先看一个最基础的语法格式:
Protocol.Property Operator Value例如:
IPv4.Address == 192.168.1.100这条规则表示“只捕获源地址或目的地址为 192.168.1.100 的 IPv4 报文”。注意,Netmon 的IPv4.Address是一个便捷属性,同时覆盖源地址和目的地址,写起来比分别写IPv4.SourceAddress和IPv4.DestinationAddress要省事得多。
运算符支持==、!=、>、<、>=、<=,也支持AND、OR、NOT。多个条件组合时,最好用括号明确优先级,避免不同 Netmon 版本解析顺序不一致带来的意外结果。比如:
(IPv4.Address == 192.168.1.100) AND (ICMP)这条捕获规则会把所有“涉及 192.168.1.100 的 ICMP 报文”抓下来,其他的都放掉。
这里有个很关键的点:Capture Filter 里能用的字段以“协议帧属性”为主,不是每个在显示区域里能看到的属性都能直接用在 Capture Filter 里。原因在于捕获过滤器工作在一个比较早的解析阶段,深层字段还没来得及被完整解析。所以我的建议是:捕获阶段尽量用“粗粒度”条件,比如协议类型、IP 地址、端口号,把流量范围缩小到你关心的边界,真正细的筛选交给显示过滤器去做。
2.2 用 Capture Filter 只抓 DNS / IP / ICMP
围绕标题里的三类流量,我整理了几个可以直接抄的捕获规则,都是我实际用过的组合。
| 需求 | 捕获筛选器写法 | 说明 |
|---|---|---|
| 只抓 DNS 报文 | DNS | 任何 DNS 数据包,包括查询和响应,都进缓冲区 |
| 抓指定主机相关流量 | IPv4.Address == 10.0.0.5 | 源或目的为 10.0.0.5 的所有 IPv4 报文 |
| 抓 10.0.0.0/24 网段 | IPv4.Network == 10.0.0.0/24 | 使用网络地址加前缀长度,注意不是掩码写法 |
| 抓 ICMP 但排除目标主机 | (ICMP) AND NOT (IPv4.Address == 172.16.0.1) | 用 AND 组合再取反 |
| 抓指定端口 TCP 流量 | TCP.Port == 443 | 源端口或目的端口为 443 都算 |
这里有一个非常容易踩的坑:Netmon 的 Capture Filter 里,IPv4.Network的写法是10.0.0.0/24,不是255.255.255.0那种子网掩码。我见过好几个同事抓了半小时发现一条包都没抓到,最后检查过滤器才发现是把掩码格式写进去了,工具没报语法错误,但匹配结果为空。所以写完过滤器后,先抓两三条已知流量验证一下,再放大规模,这是最基本的习惯。
另一个坑是,TCP.Port在 Capture Filter 里同样会同时匹配源端口和目的端口。如果你只关心目的端口 443 的入向流量,得写成:
TCP.DestinationPort == 443不要以为TCP.Port == 443只匹配了端口 443,它实际上把源端口 443 的报文也一并抓进来了,这在分析服务器出站连接时会产生“假阳性”。同理,UDP.Port也是一样,注意区分。
2.3 实战场景:抓一次 Ping 不通的排查
我举个实际场景。某天同事反馈,服务器 A 到服务器 B 的业务端口通,但 ping 不通。常规思路是抓 ICMP 报文来看请求是否发出、是否收到回包、有没有返回“目标不可达”。
在 Netmon 的捕获设置里,我直接写:
(IPv4.Address == 10.10.10.10) AND (ICMP)这个过滤器的含义:只要源地址或目的地址是 10.10.10.10,且协议是 ICMP,就捕获。然后让同事重新发起 ping,抓到几秒后停止,查看帧列表,重点看有没有 ICMP Echo Request(类型 8)和 Echo Reply(类型 0)。如果只有请求没有回应,问题多半出在 B 侧或中间链路的回包路径;如果连请求都没有,那就要去 A 侧排查,看是不是本地防火墙把 ICMP 拦了,或者 ping 命令走了其他网络出口。
这种场景如果不用 Capture Filter,整个抓包文件里全是心跳包、广播包、协议握手包,动辄几百兆,单是找 ICMP 就够费劲。用了过滤之后,文件只有几十 KB,定位快得多。
顺便说一个 Capture Filter 的限制:它无法在“帧的某个二进制偏移处”做任意字节匹配,灵活性不算高。因此,遇到需要按特定字段内容过滤,比如“只抓 DNS 响应中某个标志位为 1 的报文”,Capture Filter 做不到,必须交给 Display Filter。
3. Display Filter 实战:抓完再精准筛选
3.1 Display Filter 语法和常用字段
如果说 Capture Filter 是“粗筛”,Display Filter 就是“精筛”。它作用在已捕获、已解析的数据集上,语法比 Capture Filter 丰富得多,几乎所有的协议属性都能作为过滤条件。
基本的显示过滤器写法同样是:
协议.属性 运算符 值但运算符和值的类型更丰富,支持字符串、数字、布尔、IP 地址等类型。常见的运算符有==、!=、>、<、CONTAINS、IN等。例如:
DNS.Name CONTAINS "contoso.com"表示过滤出 DNS 字段中的名称包含 contoso.com 的报文。字符串值一定要加英文双引号,数字值和布尔值不要加引号,这个细节最容易引起语法报错。
下面整理一张我在实际排障中高频使用的字段对照表:
| 需求 | 显示筛选器写法 | 说明 |
|---|---|---|
| 只看 DNS 查询 | DNS.Flags.Response == 0 | 查询报文,Response 标志为 0 |
| 只看 DNS 响应 | DNS.Flags.Response == 1 | 响应报文 |
| 只看某域名的解析 | DNS.Name == "www.contoso.com" | 精确匹配域名 |
| 看指定 IP 的双向流量 | IPv4.Address == 192.168.1.1 | 源或目的匹配 |
| 只看 10.0.0.1 发往 10.0.0.2 | IPv4.SourceAddress == 10.0.0.1 AND IPv4.DestinationAddress == 10.0.0.2 | 单方向条件 |
| 只看 ICMP Echo 请求 | ICMP.Type == 8 | ping 请求 |
| 只看 ICMP Echo 回应 | ICMP.Type == 0 | ping 回应 |
| 只看“目标不可达” | ICMP.Type == 3 | 常见排障类型 |
| 只看“超时” | ICMP.Type == 11 | traceroute 或分片超时 |
这里有个细节值得注意:同一个含义的字段,在 Capture Filter 里叫IPv4.Address,在 Display Filter 里依然叫IPv4.Address,两者统一,这大大降低了学习成本。但在某些其他抓包工具里,捕获过滤器和显示过滤器语法完全不同,需要记两套。Netmon 这种“统一字段名”的设计,确实是它的一大亮点。
3.2 针对 DNS、IP、ICMP 的显示过滤组合技巧
实际排障中,单纯一个过滤条件往往不够,需要组合。比如要排查“客户端 192.168.1.50 访问 www.contoso.com 时为什么解析慢”,我一般会这么拆:
第一步,先确认这组流量有没有被抓下来:
IPv4.Address == 192.168.1.50 AND DNS这一步能看到该客户端相关的所有 DNS 查询和响应。
第二步,进一步限定域名:
IPv4.Address == 192.168.1.50 AND DNS AND DNS.Name CONTAINS "contoso.com"这样能看到该客户端发出的对 contoso.com 域的查询。如果查询很多但响应很慢,就要看响应报文的响应时间,或者查报文的“TCP 重传”情况。比如 DNS 查询请求重试次数多,往往是上游解析器响应慢或丢包。
第三步,如果怀疑是链路层问题,我会把 ICMP 加进来做交叉验证:
IPv4.Address == 192.168.1.50 AND (DNS OR ICMP)如果同一时间段里 ICMP 也有大量请求超时或延迟,那就不用盯着 DNS 协议本身了,先处理链路质量。
这种层层递进的显示过滤方式,比一次性写一个很长很复杂的表达式更容易定位问题,也方便逐步验证假设。
我特别要提醒一点,在 Display Filter 里写 IP 地址时,注意别把IPv4.SourceAddress和IPv4.DestinationAddress的方向搞反。服务器返回的响应,源地址是服务器 IP,所以你在过滤“服务器发给客户端的响应”时,条件应该是IPv4.SourceAddress == 10.0.0.53,而不是IPv4.DestinationAddress == 10.0.0.53。方向一错,筛选结果就是空的,很多新手在这里卡壳。
3.3 过滤器保存与复用
Netmon 的显示过滤器支持保存,可以把它理解成“收藏夹”。当你把一条过滤器在顶部的 Filter 输入栏里编辑好,并且确认它能正确过滤出想要的结果,就可以点击 Display Filter 窗口里的保存按钮,给它起一个有辨识度的名字,比如“客户端DNS请求-192168150”。
我自己维护了一套过滤器命名规范,推荐你也这样用:
- 前缀代表协议或场景,如
DNS-指定域名、ICMP-网络探测、SMB-会话。 - 中间部分写关键参数,比如 IP 或域名。
- 后面留出位置放时间批次或备注,方便追溯历史版本。
这样时间一长,积累下来一套非常适合自己工作环境的“排障工具箱”。下次遇到同类问题,直接套用过滤器,不用重新回忆语法。对于需要长期监控的场景,比如 DNS 故障、Exchange 邮件卡顿,这套复用方式能节省大量重复操作。
4. 实战演练:一次 DNS 解析异常的抓包排查全流程
理论说了一堆,不如来一次完整的案例。这个案例是我在实际工作中处理过的一个典型内网 DNS 解析超时问题,我用它来演示 Capture Filter、Display Filter、IP/ICMP 过滤怎么串联使用。
4.1 设置捕获条件
背景:某办公网内的客户端反馈,访问部分站点经常等很久才打开,偶尔直接超时。初步判断是 DNS 解析变慢。内网 DNS 服务器是 10.10.1.53,客户端是 192.168.10.88。
我在客户端上启动 Netmon,设置 Capture Filter:
(IPv4.Address == 192.168.10.88) AND (DNS OR ICMP)这里为什么要把 ICMP 一并抓进来?因为我想顺带确认网络路径是不是通。如果 DNS 解析慢的同时 ICMP 丢包率很高,那问题很可能不在 DNS 服务器软件层面,而在链路本身。举个例子,如果 ICMP 测试显示丢包高达 30%,那 DNS 查询超时大概率是网络质量造成的,而不是解析器响应慢。
接下来让同事刷新页面并重新触发解析,几分钟后停止捕获。由于过滤条件已经把范围收得比较小,文件不大,大概只有几千个帧,处理起来非常轻快。
4.2 四步定位根因
打开 Display Filter,先看整体概况。我用:
DNS把所有 DNS 报文列出来。通过“Frame Time”列,我发现到 10.10.1.53 的查询从发起到得到响应普遍在 2 秒以上,而到公网 DNS 的查询却很快。这说明客户端侧的 DNS 配置没问题,而是内网 DNS 服务器本身响应有问题。
接着把范围缩小到客户端发往内网 DNS 的查询:
IPv4.SourceAddress == 192.168.10.88 AND IPv4.DestinationAddress == 10.10.1.53 AND DNS.Flags.Response == 0再看对应的响应:
IPv4.SourceAddress == 10.10.1.53 AND IPv4.DestinationAddress == 192.168.10.88 AND DNS.Flags.Response == 1通过时间戳对比,我确认客户端发出查询后大约 200 毫秒内就收到了响应,并不是 2 秒。那我看错了吗?于是我再检查 TCP 层的情况,因为 DNS 查询通常走 UDP,但我注意到配置里 local DNS 有个 fallback 逻辑,会先尝试 UDP,没收到响应再走 TCP。我搜了一下有没有 TCP 53 端口流量:
TCP.Port == 53结果发现,客户端向 10.10.1.53 发起了大量 TCP 53 连接,三次握手能成功,但查询发起后对方迟迟不返回数据。这说明 UDP 53 被某个策略丢弃,回落到 TCP 后又因为服务端 TCP 处理异常而卡住。到这里,问题根因已经比较清晰:不是链路不通,也不是客户端配置错误,而是内网 DNS 服务器的 UDP 响应策略有问题。
4.3 用系统日志联动验证
拿到这个结论后,我没有立刻下最终判断,而是把抓包文件里 DNS 查询的时间和客户端系统日志中的 Network Profile 事件做了对照。Netmon 在 Windows 环境下有个天然优势,就是可以结合系统日志里的事件 ID 来缩小范围。查日志发现,客户端曾有多次“网络连接从公用网络切换为域网络”的记录,时间点刚好和 DNS 异常时段重叠。这进一步侧面验证了,是 DNS 服务器端点或防火墙策略在接收特定网段的 UDP 53 请求时产生了误伤。把抓包文件和时间段信息交给 DNS 管理员,对方很快定位到防火墙策略问题,调整后恢复。
这个案例里,如果一开始不用 Capture Filter,抓下来的文件会有办公网大量广播和 SMB 流量,干扰极大。而 DNS、IP、ICMP 三类过滤器分别负责了协议维度的缩小、地址维度的定向和网络连通性验证,配合使用效率很高。
5. 常见问题与排查技巧实录
5.1 高频问题速查表
下面这节总结我遇到过的高频问题,用表格形式给出,方便直接对照排查。
| 现象 | 可能原因 | 排查/解决办法 |
|---|---|---|
| Capture Filter 设置了,但抓到的文件还是很大 | 过滤器语法写错被忽略,或网卡处于混杂模式抓了大量无关包 | 检查过滤器是否生效,先跑一个小规模采样测试;确认网卡绑定的是有流量的接口 |
用IPv4.Network == 10.0.0.0/24抓不到包 | 子网格式写错,比如写成了 255.255.255.0 | 确认前缀长度写法;用IPv4.Address == 10.0.0.1单独测试 |
| Display Filter 报语法错误 | 属性名写错、值类型不匹配、运算符大小写问题 | 对照协议属性窗口里实际的属性名;数字型值不要加引号,字符串值要加引号 |
过滤DNS.Name CONTAINS "abc"没有结果 | 大小写不匹配或属性名写成了DNS.Name但实际字段是DNS.QueryName | 先不加过滤直接看帧列表,在“Details”窗口里查看实际字段名,再调整 |
| 抓包文件里没有 DNS 报文,但业务确实有解析 | 过滤器写成了DNS.Flags.Response == 1在 Capture Filter 里用 | Capture Filter 不支持这种深层属性,只能在 Display Filter 里用 |
| 显示过滤器使用后,帧数量为 0 | 属性名或值不对,或方向搞反 | 先不加过滤直接看帧列表,确认字段实际值,再逐步加条件 |
5.2 几条只有实战才会知道的技巧
再说几个纯经验层面的技巧,这些在官方文档里基本找不到。
第一,Netmon 的“Capture Settings”对话框里,启动捕获前一定看清楚选择的网络接口,无线网卡和有线网卡经常混淆。很多“抓不到包”的反馈,最后都是发现选错了接口。在命令行里用netsh interface show interface提前核对接口名称,比在 GUI 里猜要靠谱得多。
第二,抓包时尽量保持流量纯净。如果你需要分析 DNS,最好在客户端上只保留需要的网络应用,关掉后台更新、流媒体等大流量应用。虽然 Capture Filter 能挡掉大部分无关流量,但应用层并发请求多的时候,时间线错乱对排查是致命的。比如你正在等一个慢速 DNS 响应,结果后台正在下载补丁,那个时间段里的网络事件会非常杂乱。
第三,在显示过滤中用IN运算可以一次过滤多个 IP。比如同时关注隐患排查中的几台机器:
IPv4.Address IN (192.168.1.10, 192.168.1.11, 192.168.1.12)这个写法比连写一大串 OR 清晰得多,也不容易漏条件。
第四,抓包完成之后,先用“Summary”视图的协议分布统计过一遍,再决定细化过滤方向。这个习惯能避免被某一个局部现象带偏。比如你本来想查 DNS,结果统计里显示有大量的 TCP 重传,那多半链路层就有问题,先修基础网络再谈 DNS。
第五,关于 ICMP 过滤,除了 Type 8/0 之外,ICMP.Type == 3(目标不可达)和ICMP.Type == 11(超时)在排障里出现频率也很高。尤其是中间网络设备启用了 PMTUD,大包 ping 不通但小包能通的时候,重点抓 Type 3 的“Fragmentation needed”子类型,直接能找到 MTU 瓶颈。
6. 再交代一句工具本身的边界
最后还是把丑话说在前面。Microsoft Network Monitor 3.4 毕竟是十多年前的工具,对 TLS 1.3、QUIC、HTTP/2 等新协议的支持基本是空白,解析出来的 TLS 层信息非常有限。如果你要深入分析现代加密流量,或者需要跨平台抓包,Wireshark 依然是最优解。但 Netmon 在 Windows 内网环境的价值并没有因此消失,尤其是微软协议族和事件关联分析的场景,它依然有不可替代的生态优势。
很多朋友纠结“到底学哪个”,我的建议是:以 Wireshark 为主力,把 Netmon 当 Windows 环境下的备用利器。两边筛选器思路其实是相通的,你今天在 Netmon 里练会的 Capture/Display 两段式过滤逻辑,挪到 Wireshark 里同样管用。我自己的习惯是,处理纯 Windows 或微软协议栈问题时优先开 Netmon,其余场景默认 Wireshark,两者并不冲突。
最后分享一个小习惯:执行完一次抓包排查后,记得把用过的过滤器表达式、当时的网络拓扑、结论一并记录到一个文档里。时间久了,这套笔记会比任何教程都更贴近你的实际环境,下次遇到类似问题时,几乎可以照着文档直接复现整个排查流程。