搞网络的人,迟早会跟 Wireshark 打交道。这工具在网工手里是排障利器,在开发手里是协议调试神器,在不熟悉的用户眼里就成了"一堆看不懂的乱码窗口"。我第一次被它彻底征服,是某次线上系统频繁卡顿:后端说网络没毛病,运维说服务器负载正常,最后抓包一看,某个客户端的大报文在链路上反复重传,问题一下水落石出。从那以后,Wireshark 就成了我排障工具箱里的保留项目。
这篇内容就是一次完整的 Wireshark 抓包实战演示。我会从选接口、配置过滤器开始,带着你把一个 HTTP 请求从三次握手到响应回包整个看一遍,再用常见故障案例演示如何定位问题。看完之后,你至少能独立抓包、能看懂常见协议交互、能处理工作中的大部分网络疑难杂症。网工、运维、后端、客户端开发、安全测试同学,甚至在校学生都能用得上,建议先收藏再慢慢看。
1. 抓包背后的原理与适用场景
1.1 数据包是被怎么"截获"的
Wireshark 抓包,本质上是把经过网卡的数据包复制一份给用户态程序分析,对原有数据链路没有任何干扰。你可以把它理解成在门口装了一个摄像头:进出的人该走还走,只是有一份记录被额外保存了下来。
这个"复制"动作靠的是底层库。Windows 上通常是 Npcap,Linux 上是 libpcap 或者 AF_PACKET 机制;Wireshark 只是把底层库拿到的数据做协议解析和界面展示。这也是为什么 Wireshark 安装时会让你单独勾选 Npcap,如果底层组件缺失,界面再好看也抓不到包。
网卡默认有个工作状态叫"非混杂模式",它只处理目标 MAC 地址是自己、广播或组播的包。抓包工具要看到更多流量,就需要把网卡切到混杂模式,让所有经过的帧都被接收。但这里有个常见误区:现在局域网大多用交换机,交换机会按 MAC 地址表精确转发,你就算开了混杂模式,也未必能看到同一交换机下其他电脑的流量,除非中间有镜像端口或者使用集线器。所以抓包要调整预期,别指望插上网线就能围观全楼流量。
1.2 哪些问题适合让 Wireshark 出场
开发或运维过程中,有些问题光靠日志很难定性,比如:
- 接口明明在服务器上很快,客户端却体验卡顿,到底慢在哪一步。
- 两个系统之间对接,双方都觉得自己发送的数据是对的,但对方收到就是不对。
- 页面偶发打不开,报错一闪而过,想确认是 DNS 解析问题、TCP 连接问题,还是 HTTP 层问题。
- 自己和对方都在做联调,谁先发起的断开,连接被谁重置。
- 手上没有源码,只有个二进制客户端,想知道它到底向服务器发了什么。
这些场景,Wireshark 几乎是最直接的答案工具。它能同时给出时间线、协议栈和原始字节流,把"看不见的网络交互"变成可回放的数据。相比 ping、telnet 这些零散工具,抓包的优势在于"全过程记录",一次抓包就能把 DNS、TCP、TLS、HTTP 各层串联起来看,非常适合复杂链路排障。
2. 准备环境:选对网卡是成功的一半
2.1 安装与权限要先过关
安装 Wireshark 时,Windows 用户务必把 Npcap 一起装上,版本和系统位数匹配好。装完之后如果提示 Npcap 未运行,多数情况是只装了 WinPcap 或者 Npcap 服务被禁用。现在的 Wireshark 默认走 Npcap,老教程里说装 WinPcap 的做法已经过时。
Linux 下如果以普通用户启动,可能会提示权限不足,无法打开 /dev/bpf* 或权限受限。解决办法是把用户加入对应组,或者用 sudo 运行。macOS 也有类似情况,首次运行会要求授权安装权限包,这一步不能跳过。我建议日常分析至少先用普通权限熟悉界面,遇到抓不到包了再查权限配置,别一上来就 sudo 跑,容易养成坏习惯。
2.2 怎么选正确的接口
Wireshark 启动页会列出所有可用网卡,每张网卡后面还有一个实时的流量波形图。选接口的核心原则:看你要抓的对象走哪个网卡。
访问外网的服务,就选实际的物理网卡,比如以太网或 WLAN。如果你在用无线,注意部分无线网卡驱动不支持彻底混杂模式,只能收到自己收发或广播的包,这在排查自己这台机器的问题时也够用了。如果要抓虚拟机或容器流量,就得选对应的虚拟网卡,然后在虚拟机内部再抓也行。
还有一个高发坑位:电脑同时开了"以太网"和"WLAN"两块网卡,但流量实际走的是一块,你选错了自然什么都看不到。我习惯的做法是抓包前先看接口详情里的 IP 地址,确认哪张网卡持有目标网段的地址。启动页的波形只能说明有流量经过,不能说明是你关心的流量。
2.3 三个推荐提前关掉的设置
我用 Wireshark 每到一个新环境,调整这三处才觉得顺手:
第一,关闭名称解析。默认情况下 Wireshark 会做 DNS 反查和 MAC 厂商查询,好处是 IP 会显示成域名,但代价是抓包过程会额外发起大量 DNS 请求,拖慢界面,有些内网 IP 解析半天还会超时。在 捕获 -> 选项 里,把名称解析的三个勾都取消,界面会清爽得多。
第二,开启自动滚动。抓包时数据实时刷新,窗口默认停在上方,你得手动往下拉,很容易错过关键包。在视图菜单里打开自动滚动,新包就会一直在视野中。
第三,把时间列改成相对时间。默认绝对时间看不出间隔,排查慢请求时需要的是"第几个包离上一个包隔了多久"。在 视图 -> 时间显示格式 里选"相对时间(秒)"格式即可。这几步做完,建议 Wireshark 会默认保存你的配置,下次打开不用再调。
3. 第一次实战演示:抓一个 HTTP 请求的完整流程
3.1 操作全流程走一遍
准备阶段就绪后,开始第一次抓包。我以访问某个测试站点为例,你可以换成任意 http 开头的站点。
步骤很简单:打开 Wireshark,双击你要用的网卡,看到顶部绿色波形滚动表示正在抓包,然后在浏览器里访问测试地址,等待页面加载完成后回到 Wireshark,点击红色方块停止抓包。
这时候你会看到几十上百个包,眼花缭乱。先在过滤栏输入 http,回车,就只剩 HTTP 协议相关的包。如果你访问的站点是 https,就会看不到 HTTP 明文,只能看到 TLS 协议,这是加密流量,普通抓包方式下内容不可读,关于 HTTPS 的解密我后面会专门讲。
3.2 跟随三次握手和 HTTP 报文
筛选出 http 后,找到最前面那条 "GET / HTTP/1.1" 的请求包。点中它,你会看到下方分栏里依次展开的协议树:Frame、Ethernet II、Internet Protocol Version 4、Transmission Control Protocol、Hypertext Transfer Protocol。
在它前面,应该还有三个没显示在 http 过滤里的 TCP 包,因为它们不是 HTTP 协议。想看完整互动,把过滤改成 tcp,清空 http 条件,找到客户端发起连接的第一条包,状态是 SYN。可以按 Ctrl+Alt+N(或看包颜色的红色标记)快速找。真正完整的过程是:SYN,SYN+ACK,ACK,这就是常说的 TCP 三次握手。
这三次握手解决什么问题?想象打电话:先拨号(给你一个 SYN),对方接起来说"听到了吗"(回一个 SYN+ACK),你再回一句"听到了"(ACK),然后才开始说正题。只有连接建立好,浏览器才会把 GET 请求发出去。后续的发包和确认也是这个道理:TCP 保证每个字节都按顺序送到,丢了就重传,慢了就有延迟。
3.3 用 Follow Stream 看完整会话
只看单个包不够直观,你可以在任意一条 HTTP 包上右键 -> 追踪流 -> TCP 流。Wireshark 会把客户端第一次发送到连接结束前所有应用层字节拼在一起,打开一个文本窗口,左边是浏览器发给服务器的内容,右边是服务器返回的内容。这个功能特别适合联调接口时"对暗号":双方说自己发了什么,一跟流就能看到真实报文里写的什么。
在这个窗口里你能看到 HTTP 请求行、Header 字段、空行、Body,也能看到响应状态行、响应头、Content-Length 等。我建议新手把窗口里的内容拉一遍,对比一下浏览器开发者工具里的 Network 面板,两者本质是同一份数据,但 Wireshark 的视角更底层,还会包含连接时序细节。
4. 过滤器语法:抓包效率和准确性的分水岭
4.1 两种过滤器别搞混
Wireshark 有两套过滤体系:捕获过滤器和显示过滤器。
捕获过滤器是在数据落地之前就过滤,符合条件的数据包才保留。它语法香短,属于底层 BPF 语法,过滤条件只能在抓包启动前设置,一旦抓起来就不能改。常见的写法是 host 1.2.3.4、port 443、tcp portrange 8000-9000。
显示过滤器则是对已经抓到的包做二次筛选,语法更丰富,支持协议字段级过滤,比如 http.request.method == "GET"、tcp.analysis.retransmission。它最大的优点是随时改、反复改,不影响原始抓包数据。
新手最容易犯的错是把显示过滤器表达式往捕获过滤器窗口里填,发现语法报错。记住一个简单原则:紧张时刻、范围不确定时,就用显示过滤器;只有你明确知道只要某个 IP 或某个端口的流量、并且希望文件尽量小,才用捕获过滤器。
4.2 高频显示过滤器速查
下面这些表达式基本覆盖了 90% 的日常排障使用。可以保存成按钮放在过滤栏里。
| 目标 | 表达式 |
|---|---|
| 某个 IP 的上行下行 | ip.addr == 10.1.1.88 |
| 只看某个端口 | tcp.port == 8080 |
| 只看 HTTP 请求 | http.request.method == "GET" |
| 只看 HTTP 响应 | http.response.code == 500 |
| 只看 DNS 响应 | dns.flags.response == 1 |
| 只看重传包 | tcp.analysis.retransmission |
| 只看 SYN 包 | tcp.flags.syn == 1 and tcp.flags.ack == 0 |
| 只看 RST 包 | tcp.flags.reset == 1 |
逻辑运算符也跟普通编程相似,与是 and,或是 or,取反是 !。比如你想排除一个噪音 IP,可以写 ip.addr != 10.0.0.8;但要特别注意,使用 != 存在一个隐藏坑:如果包里同时有源和目的两个 IP 字段,ip.addr != x 只要任一字段不等于 x 就会保留,结果可能和你预期不同。更保险的写法是 !(ip.addr == x)。
4.3 右键是你最好的老师
过滤器不用死记。在包列表里看到某个字段,右键 -> 作为过滤器应用 -> 选中,Wireshark 会自动生成一条表达式。看到一条报文,只要判断它是不是你关心的数据,点两下就能完成筛选。用多了自然就记住了。
还有一个技巧:过滤栏支持输入提示,你敲 tcp. 之后会弹出自动补全列表,再点一个字段出来,那个字段的含义在下方会有说明。记不住表达式的时候,把鼠标悬停在上面的字段名,Wireshark 会给出该字段的完整路径和类型提示。
5. 实战排障演示:定位"页面加载很慢"问题
5.1 环境与现象描述
某公司有一个内部业务系统,某天接到反馈:部分用户在办公室里打开页面时,经常要等 5 秒到 6 秒才出内容,偶尔直接超时,刷新又能好。后端去查服务端日志,发现接口处理时间很正常,数据库也没慢查询。这时我就会在客户端做一次抓包,看看等待时间到底耗在哪一跳。
抓包操作:选好办公网对应的网卡,在捕获选项里加一条捕获过滤器 host 业务系统IP 或 port 443,减小文件体积。抓包持续 3 到 5 分钟,期间让报障同事重新打开页面几次,然后停止抓包,保存文件,开始分析。
5.2 第一处异常:SYN 重传
打开保存好的文件,先过滤到目标 IP:ip.addr == 业务系统IP。如果你看到某个客户端 IP 对服务器 IP 发送了 SYN,隔了大概 1 秒又发一个 SYN,再隔 2 秒又发一个,然后隔 4 秒再发,那就是 TCP 连接层在做重传。
TCP 是可靠传输,连接请求发出去后如果迟迟没收到回应,发送方就会按重传超时机制重发 SYN,而且每次重传间隔会指数增长:1 秒、2 秒、4 秒、8 秒……如果重传了 3 次,光建立 TCP 连接就可能花掉好几秒,跟"页面白屏 5 秒"的现象完全对得上。
筛选方式可以这样:tcp.flags.syn == 1 && tcp.flags.ack == 0 && tcp.analysis.retransmission。在 Wireshark 里,重传包在列表的 Info 列会显示 [TCP Retransmission],非常显眼。说明 SYN 包在链路上的某个中间环节被丢弃,或者没有回包。结合现象"过段时间又好了",基本是防火墙、负载均衡或中间网络设备策略偶发丢包。
然后我再抓本机 ping 同一目标 IP 做对比,如果 ping 稳定,说明小包能通但大包可能被限制,或者只是 TCP 特定端口被拦截。这里可以继续验证明路,但核心已经定位:不是后端慢,是 TCP 连接建立阶段网络丢包率高。
5.3 第二处问题:DNS 查询超时导致解析失败
同一次抓包里,我还发现了一个现象:访问某些资源时,客户端发起 DNS 查询,等了 3 秒多才出现第二个查询请求,再等几秒才有响应。过滤 dns,看到请求与响应的对应关系时,重点看 Info 列的编号是否一一对应,以及响应包来源。
通过 DNS 部分的包时间戳就能算出,解析域名一次就花了 1 到 2 秒,这类延迟叠加在页面加载上,体验当然很差。进一步看请求发往哪个 DNS 服务器、响应来自谁,如果出现"客户端向自己配置的 DNS 服务器发了很多次查询,但一直没回包",问题就指向内网 DNS 不可达或服务异常。
当时我让同事用 nslookup 手动解析了两次确认,一次失败一次成功,这跟抓包结论一致。解决办法是检查客户端配置的 DNS 服务器到客户端路由是否正常,以及 DNS 服务本身的负载;在这个案例里换掉历史遗留的首选 DNS IP 后,解析耗时回落到毫秒级。
5.4 排查链路怎么串起来看
结合两处异常:SYN 重传和 DNS 超时都指向网络路径不稳定,但表现不一样。HTTP 层的白屏只是一个结果,从抓包看,光是 TCP 握手和 DNS 解析就消耗了绝大多数时间。
排查这类问题最忌讳只盯一个层次。Wireshark 的价值就在这里:它把 DNS、TCP、TLS、HTTP 按时间轴排好,让你一分钟内看清"慢"在哪一层。如果只看后端日志,你会以为客户端有问题;如果只看浏览器控制台,你会发现"等待服务器响应"时间很长,但不知道哪段网络慢。抓包能给出一条明确的证据链。
6. 常见问题与排查技巧实录
6.1 为什么总是抓不到想要的包
这个提问在所有新手用户里出现频率最高。我总结下来主要是五个原因:一是接口选错,流量根本不经过当前选中的网卡;二是显示过滤器把包过滤掉了,看起来抓不到,其实数据在原始包里;三是权限问题,抓包工具没拿到管理权限;四是混杂模式没生效,无线网卡或虚拟网卡尤其常见;五是抓包范围本身不对,客户端和服务器之间的流量在其他链路上。
排查思路也很简单:先不设置任何过滤器,只选网卡抓 10 秒,如果能看到大量 ARP 或其他协议包,说明工具本身在工作;再手动访问目标并停止抓包,搜索目标 IP 或域名,仍然找不到,大概率是方向错了。我习惯在抓包前先用下面的命令确认本机路由:ip route 或 route print,看目标地址走的是哪个接口。
6.2 HTTPS 流量全是密文,还能分析吗
现在多数站点都是 HTTPS,直接抓包只能看到 TLS 握手和密文数据。但这不意味着 Wireshark 彻底无解。调试自己掌握密钥的应用程序时,可以通过设置环境变量 SSLKEYLOGFILE,让浏览器或应用把 TLS 会话密钥写进日志,然后在 Wireshark 的 编辑 -> 首选项 -> Protocols -> TLS 里指定该日志文件,抓到的 HTTPS 流量就能解密成明文 HTTP。
这个方法有几个要求:必须是你自己有权限控制的客户端和服务端环境;密钥日志文件要妥善保存,别乱传;整个过程只适合开发和测试环境,线上环境和他人网络不能这么干。如果你的场景不满足条件,那就接受现实,把 TLS 握手阶段当成分析重点——握手用了几个往返、证书链是否完整、client hello 是否异常,这些也能解决不少问题。
6.3 抓包文件太大,一打开就卡死
有些人习惯打开抓包就开始录,几分钟下来文件大几百兆,再用 Wireshark 打开慢如蜗牛。解决方式有两个方向。
一个是事前控制:启动捕获时用捕获过滤器缩范围,比如只抓 tcp port 443 或 host 指定IP。另一个是打开文件时选择"只读头几 KB"或按时间范围切割,用自带工具 mergecap 和 editcap 可以拆分。还有一个办法是分段保存:在捕获选项里启用多文件模式,设一个文件大小上限,比如 100MB,Wireshark 会自动生成连续文件,分析的时候只需要处理自己关心的那段。
6.4 常见抓包问题速查
| 症状 | 可能原因 | 优先动作 |
|---|---|---|
| 提示未安装 Npcap | 漏装或驱动被禁用 | 重装 Npcap,版本匹配系统 |
| 抓到包但列表全空 | 权限不足 | 以管理员权限重新打开 |
| 只有自己的流量 | 无线网卡混杂模式受限 | 改用有线网络或在目标主机上抓包 |
| 看不到 HTTP 明文 | 访问是 HTTPS | 按上文方式配置 TLS 解密 |
| 过滤器语法报错 | 显示过滤器混入捕获过滤器 | 检查两种定义的适用范围 |
| 界面卡顿严重 | 抓包过程启用了 DNS 解析 | 关闭名称解析 |
6.5 别迷信专家信息,但也别不用
Wireshark 左下角的"专家信息"会按严重程度列出错误、警告、注意和聊天级别的提示,比如重传、乱序、窗口缩小等。对于新手,这个界面是很好的线索入口;但我见过不少人看到两三条警告就草率下结论,结果带歪了排查方向。
专家信息只是根据协议栈规则给出的启发式提示,比如 "TCP Dup ACK" 不一定代表网络有故障,可能只是接收端的正常探测。我的建议是:把专家信息当线索集,真要下结论,还是要回到具体包上看时间戳、序号和标志位。一次完整的排障,通常要用到 专家信息 + 显示过滤器 + Follow Stream 三件套。
7. 最后分享两个实战心得
第一个心得是:抓完包优先保存,再开始分析。Wireshark 的临时缓冲区会在停止后保留一段时间,但机器重启、内存压力大或软件异常退出都会让你白抓一场。我习惯是停止抓包后立刻 Ctrl+S 保存为 pcapng 文件,再在保存的文件上继续筛选。这样做还有个额外好处:你可以反复查看同一条网络连接的不同维度,不必担心界面上误操作丢数据。
第二个心得是:带着问题去抓包。漫无目的地抓半小时,往往得到海量噪音,反而找不到重点。想清楚"我要确认什么"再抓,比如确认 TCP 握手是否顺利、确认某个接口是否被调用、确认响应包是否丢失,这样抓出来的数据小而精。抓到之后,先看连接的三次握手是否干净,再看应用层报文是否符合预期,最后再看时间线。这套顺序我用了很多年,对绝大多数网络问题都适用。抓包不难,难的是把海量细节组织成一条清晰的证据链,而 Wireshark 恰好能帮你完成这一步。