Wireshark排障实战:从抓包过滤到协议分析,快速定位TCP重传问题

发布时间:2026/10/22 10:32:53
Wireshark排障实战:从抓包过滤到协议分析,快速定位TCP重传问题 做了这么多年一线网络排查Wireshark基本是我每天都会打开的工具。但说实话我见过的大部分使用者其实只把它当成一个高级一点的“抓包器”选网卡、点开始、抓完收工然后对着十六进制面板发呆。真正让Wireshark和普通抓包工具拉开差距的是它的分析和解码能力——你先要能看出“哪段流量有问题”再看懂“这段流量里到底发生了什么”。这篇文章我就把日常排障里真正用得上的分析思路和解码手法从打开软件之前一直讲到遇到乱码协议怎么自定义解析适合所有被TCP重传、看不懂协议头、对不上的请求响应折磨过的朋友。1. 打开软件之前先把抓包场景想明白1.1 选接口、开混杂模式、找准抓包位置多少人第一次抓包失败是因为压根选错了网卡。Wireshark启动首页列出的是一堆接口名称常见的有以太网、WLAN、以及各种虚拟网卡。如果你要抓本机和外部的正常通信就选当前有流量、状态不是“无数据包”的那个物理网卡如果抓的是本机进程之间或回环地址的通信比如本机连本机的某个端口就必须选Loopback环回接口选普通物理网卡是看不到回环流量的。选完接口还有个隐藏前提确认网卡的“混杂模式”已开启。默认情况下网卡只会把发给自己的帧交给系统开了混杂模式才能让网卡把经过它的所有帧都收上来。Wireshark的捕获选项里每个接口旁边有个“启用混杂模式”的开关大多数场景下建议勾选。但这里有个现实问题——在普通交换机的网络里即使开了混杂模式你也只能看到发到自己这台机器的单播流量和所有广播流量看不到别人两台机器之间的通信。想抓别人设备的包要么在汇聚交换机上做端口镜像SPAN要么用TAP设备串接要么就直接在这台设备上抓。这一点如果没有提前想清楚后面就会陷入“明明开了混杂模式却什么都抓不到”的死胡同。1.2 捕获过滤器抓包阶段就把流量切窄很多人一上来就点“开始”把整个网卡的流量都抓到本地几分钟后就发现文件已经几百MBWireshark开始卡顿分析心情全无。正确做法是在抓包开始前就想好“我只关心哪部分流量”用捕获过滤器Capture Filter在最前端把数据切掉。捕获过滤器走的是BPF语法常见写法如下# 只抓指定IP和指定端口 host 192.168.1.10 and tcp port 443 # 抓整个网段忽略广播组播 net 192.168.1.0/24 and not broadcast and not multicast # 只抓HTTP和DNS port 80 or port 53 # 排除某个IP的干扰流量 host 192.168.1.10 and not host 192.168.1.20之所以强调在“抓包阶段”过滤而不是抓完再过滤原因有两个。第一是性能大量无关流量会填满抓包缓冲区在高流量链路上甚至会造成内核丢弃数据包也就是Wireshark状态栏里那个“X packets dropped”提示第二是文件体积一个几百MB的pcap在打开和筛选时都很痛苦而抓包阶段过滤后的文件往往只有几MB后面想怎么看都轻松。如果你确实需要长时间守候某个偶发问题可以把抓包文件配置成“环形缓冲区”在捕获选项里勾选“使用多个文件”每个文件设置大小或时长比如每个文件20MB、共10个文件旧文件会被自动覆盖。这招夜里挂机抓包特别实用不用担心睡一觉起来磁盘满了。2. 显示过滤器把一堆包变成一行结论2.1 语法骨架和几个容易踩的坑捕获过滤器只是前置筛选真正高频使用的是显示过滤器Display Filter它把已抓到的海量数据快速筛选成你关心的部分。显示过滤器的语法和BPF不同但它设计的核心逻辑是一致的字段 条件 逻辑组合。先看最基本的骨架# 等值比较 ip.addr 192.168.1.10 tcp.port 443 http.request.method POST # 大小比较 frame.len 1500 tcp.window_size_value 1024 # 包含匹配 http.host contains api dns.qry.name contains example # 协议存在判断 tls.handshake icmp逻辑组合使用and、or、not也可以用、||、!。比如说“这个IP的HTTP请求或者与这个端口相关的所有TLS流量”(ip.addr 192.168.1.10 and http.request) or tcp.port 443括号非常关键。显示过滤器的解析顺序里and的优先级高于or如果不加括号结果会完全不符合你的直觉。这一点我觉得几乎每个季度都会有人踩一次。还有个更经典的坑ip.addr 1.1.1.1 and ip.addr 2.2.2.2看起来是矛盾的因为一个包不可能是两个不同IP。但实际执行结果往往不是空集因为ip.addr字段同时覆盖了源地址和目的地址两个值。“这个包的源地址或目的地址是1.1.1.1”且“这个包的源地址或目的地址是2.2.2.2”只要流量发生在两个IP之间条件就成立。想表达“从1.1.1.1到2.2.2.2”要写成ip.src 1.1.1.1 and ip.dst 2.2.2.2。这是新手最容易误解、老手也可能因为马虎翻车的细节。2.2 高频场景过滤器速查表我把自己平时用得最多的过滤器整理成了一张表每次排查都能直接套场景显示过滤器只看某个IP的全部流量ip.addr 192.168.1.10只看HTTP请求和响应头http或细分 http.request只看DNS查询dns.flags.response 0只看TCP重传tcp.analysis.retransmission只看重复确认tcp.analysis.duplicate_ack只看可疑窗口更新tcp.analysis.zero_window只看TLS握手包tls.handshake.type两个包间隔超过0.3秒frame.time_delta_displayed 0.3只查特定字符串的负载frame contains keyword这里特别提一下tcp.analysis.*系列。它不是抓到的某个真实字段而是Wireshark在后台根据TCP状态分析后生成的“专家结论”。比如tcp.analysis.retransmission会直接标出重传包这在排查丢包、延迟问题时能省掉大量肉眼找包的功夫。使用tcp.analysis时一定要注意一点它依赖完整会话上下文如果你抓包时漏掉了一部分流量分析结果可能不准确。3. 流量解码从原始字节到业务字段3.1 追踪TCP流把会话还原成对话抓到的包如果只是一个个孤立的数据帧看起来就是一堆十六进制乱码。Wireshark的“追踪TCP流”功能是理解复杂交互最直接的入口。右键选中任意一个TCP包选择“跟随TCP流”Wireshark会把该TCP连接从三次握手到断开的所有负载拼成一个连续的对话视图。这个功能特别适合排查接口联调问题。比如说你怀疑某个接口偶发超时直接定位到一个POST包跟随TCP流就能在同一个窗口里看到客户端发的完整请求、服务端返回的完整响应时间线上谁先谁后一目了然。流窗口里默认显示的是“C/S”双向混合如果你只想看某一方向的发送内容也可以通过下拉切换这个在做协议模拟回放时很有用。HTTP场景下还有更贴心的“导出HTTP对象”功能在菜单栏“文件 → 导出对象 → HTTP”里能看到这次抓包里所有HTTP响应中携带的文件资源比如图片、JS脚本、下载的安装包。排查网页加载慢的时候我会先看导出的对象列表里哪个文件传输时间异常再顺藤摸瓜看对应的TCP连接。3.2 揭开HTTP压缩与HTTPS加密HTTP流量看似“明文”但很多实际场景里内容是被压缩的。客户端请求头里的Accept-Encoding: gzip, deflate, br暗示了服务端可能返回压缩内容如果直接在流窗口里看到一堆二进制乱码不要怀疑是抓错包多半是压缩负载。Wireshark默认会在解码层面尝试解压常见格式但如果解压失败或想手动看原始内容可以到“编辑 → 首选项 → 协议 → HTTP”里调整相关设置比如是否启用解压缩、是否解析分块传输编码。HTTPS则是另一层难题。Wireshark默认只能看到TLS握手和加密后的密文想看明文有两种路径。第一种在“首选项 → 协议 → TLS”中配置RSA密钥或Key Log FileKey Log File常见于浏览器、部分应用框架开启SSLKEYLOGFILE调试环境变量时导出的会话密钥文件。只要拿到这个文件Wireshark就能自动解密对应会话。第二种用中间人代理的方式让流量经过你控制的证书和记录点——但这是另一个话题了实际场景中牵扯证书信任问题不是每次都能做。我的经验是解密HTTPS虽然是刚需但不要一开始就陷进去。很多排障场景其实不依赖明文。比如判断接口是不是握手慢看TLS握手阶段的tls.handshake.type和两个方向的时间间隔就够了判断是不是证书校验失败看tls.alert和tls.handshake.certificate即可。明文只是最终诉求不是中间分析的必要条件。4. 自定义协议解码当Wireshark不认识你的时候4.1 强制解码和协议首选项日常工作中最头疼的不是标准协议而是自研协议或私有协议。比如某套设备基于TCP 6000端口自定义了一套二进制报文Wireshark不认识它只会把它当作普通TCP负载展示所有业务字段都混在一起。第一步可以尝试“解码为”功能右键任意一个TCP包选择“解码为…”在对话框里指定端口对应的协议。如果你知道这端口跑的是JSON格式直接指定为HTTP那些“GET /raw”和响应头就会被解析。如果数据本身是Modbus/TCP、DNP3等工业协议但用了非默认端口也可以在“解码为”里手动绑定。如果目标协议是标准协议但端口不标准更稳妥的做法是修改协议首选项。以Modbus/TCP为例在“首选项 → 协议 → Modbus/TCP”里添加自定义端口这样Wireshark每次遇到这个端口的数据都会自动按Modbus解析不用反复手动“解码为”。遇到Wireshark本身不认识的协议还有个快速试错的办法先把它当成十六进制原样看找出固定字段位置再决定是否值得写个解析脚本。绝大多数情况下私有协议都会包含“魔数/长度/类型/负载”这样的结构你可以先手工翻几个包验证规律再进入下一步。4.2 用Lua写一个迷你解析器直接挂到端口上Wireshark的Lua脚本扩展能力被很多人忽略了其实写一个能识别并解析私有协议的迷你dissector并不复杂。下面这个例子针对一个假想的UDP协议包结构是1字节类型、2字节长度、后续为长度对应的负载。local my_proto Proto(MyProto, My Custom Protocol) local f_type ProtoField.uint8(myproto.type, Type, base.DEC) local f_len ProtoField.uint16(myproto.length, Length, base.DEC) local f_payload ProtoField.bytes(myproto.payload, Payload) my_proto.fields { f_type, f_len, f_payload } function my_proto.dissector(buffer, pinfo, tree) if buffer:len() 3 then return 0 end local type_val buffer(0,1):uint() local len_val buffer(1,2):uint() if buffer:len() 3 len_val then return 0 end pinfo.cols.protocol MYPROTO local subtree tree:add(my_proto, buffer(), My Custom Protocol) subtree:add(f_type, buffer(0,1)) subtree:add(f_len, buffer(1,2)) subtree:add(f_payload, buffer(3, len_val)) pinfo.cols.info string.format(Type%d Len%d, type_val, len_val) return 3 len_val end local udp_table DissectorTable.get(udp.port) udp_table:add(40000, my_proto)把以上内容保存为myproto.lua放到Wireshark的插件目录里。“帮助 → 关于 → 文件夹 → 个人配置/Lua插件”会为你打开那个目录。重启Wireshark后凡是UDP端口40000的包就会自动按这个协议解析协议列显示“MYPROTO”详情面板出现Type、Length、Payload三个字段可以直接点开十六进制逐字节核对。这个脚本里有两个值得注意的细节。一是提前做长度校验避免解析器读取越界导致Wireshark崩溃或报错二是用return 3 len_val明确告诉上层这个包消费了多少字节否则某些隧道协议里字段偏移会错位。如果你熟悉C语言写dissectorLua版的原理是完全相通的只是省去了编译步骤。另外如果你的协议不是固定端口而是希望根据负载特征识别比如看到某段“magic bytes”就判定为协议A那需要写的是启发式解析器Heuristic Dissector在Proto里注册pinfo层次上的heur回调。这类脚本会比固定端口版本复杂一些但对真正在业务里跑私有协议的人来说投入产出比极高。5. 用TCP分析器定位性能问题5.1 看懂专家信息不是所有红色标记都是故障Wireshark的主界面下沿有个“专家信息/Expert Info”入口把所有分析类提示按严重程度分组。很多人一看到红色“错误/Error”就慌其实这些提示里相当一部分是正常现象。比如TCP Previous segment not captured翻译过来是“前面的报文没抓到”这往往表示抓包点位于会话中间或者流量经过了本地看不到的路径不代表业务丢包。又比如ACKed unseen segment同样可能是抓包起点的偏移。真正的危险信号主要集中在这几类tcp.analysis.retransmission当前包是对之前某个包的重传说明对方可能没收到或ACK丢失。tcp.analysis.duplicate_ack接收方连续重复确认同一个序号通常意味着后续段丢失或乱序严重。tcp.analysis.zero_window接收方窗口变为0表示它的接收缓冲区已满业务层处理不过来。tcp.analysis.spurious_retransmission因为延迟或乱序触发的“误判重传”有时不是网络丢包而是路径延时抖动。我给出的建议是把专家信息当成一个索引不要当成判决书。看到红色提示后回到对应的数据包和上下文里核实看它前后到底发生了什么。有一次某客户报“下载速度慢”打开专家信息全都是“Dup ACK”我一开始也以为是丢包后来点进去细看发现是接收端开启了延迟ACK合并加上TCP窗口收缩导致接收方重复确认了同一批数据真实原因其实是应用层读缓冲区太小。光看结论不看上下文一定会被误导。5.2 RTT、重传和那张Time-Sequence图排查性能问题我最常用的路径是先显示过滤出tcp.analysis.retransmission || tcp.analysis.fast_retransmission || tcp.analysis.duplicate_ack确认有无大量重传再打开“统计 → TCP流图 → 时间序列(Stevens)”把整个连接的行为画出来。这张图横轴是时间纵轴是TCP序列号。一个健康的长连接图形应该像一条稳定向右上攀升的斜坡如果斜坡某处出现下降或平台意味着对应序列号的数据一直没推进往往就是重传窗口。再看斜率是否平缓或周期性抖动能直观判断外网带宽瓶颈还是内网拥塞。举例来说有一次排查一个“上传文件龟速”的问题用Time-Sequence图发现数据上升完全符合带宽上限但每几秒就会出现一个明显向下的“锯齿”——这是发送方不断回退序号重传。进一步看RTT发现ACL只针对某个方向的SYN做了延迟处理导致握手和部分包被重排。最后定位到的是网络路径上的中间设备策略而不是服务器问题。如果不看图单靠数重传包数量很难看出这种周期性规律。单看瞬时RTT也有技巧在首选项里把TCP显示的“时间列”调成相对的帧间时间然后在包列表里找第一次发送和ACK返回的时间间隔。你可以在“统计 → TCP流图 → 往返时间”里看到整个连接RTT的散点分布从中找到异常尖峰对应的准确时间点再回到抓包里结合时间戳看当时发生了什么。6. 常见问题与排查技巧实录6.1 抓不到包、抓到了却显示校验错误最常见的“抓不到包”原因我在开头提过接口选错、混杂模式没开、交换机端口镜像没配。除此之外还有个容易被忽略的场景——无线网卡。大多数Wi-Fi网卡即使开了混杂模式也只能抓自己连接的这个BSS内的流量很难像有线网卡那样随便监听别人。所以排查无线问题最好在对应AP的镜像口抓或者在终端本身上做本地抓包。第二种典型现象是抓包软件里显示一堆TCP/IP校验和错误。看到这种情况不要急着断言“网卡坏了”先确认是不是硬件卸载Hardware Offload导致的。很多网卡在发送报文时会自动计算并填充IP和TCP校验和抓包工具拿到的只是操作系统传给网卡之前的“空壳”于是Wireshark会把校验和标为错误。这属于误报。要消除误报可以在 Windows 设备管理器中关闭网卡的“Large Send Offload”和“TCP/UDP Checksum Offload”或使用某些网卡驱动自带的高级设置Linux下可以尝试用ethtool -K 接口名 tx off rx off关闭相关卸载能力。6.2 大文件、卡顿、过滤结果出不来抓取文件太大导致Wireshark界面卡成PPT是所有分析人的痛点。几个实用对策用editcap按包数切分文件比如希望每份不超过10万包editcap -c 100000 原始文件.pcapng 分卷.pcapng。切完分别分析定位到具体时间窗口后再细看。用mergecap把多个分散抓包合并成一个有序文件。用tshark在命令行直接提取字段避免打开巨大的GUI。比如把HTTP请求的主机名和URI全部导出tshark -r big.pcapng -Y http.request -T fields -e ip.src -e http.host -e http.request.uri -E headery requests.txt这样几万个HTTP请求几秒钟就能导出结构化表格比在GUI里一页页翻高效得多。如果用了显示过滤器仍然慢还可以考虑先把范围缩小到目标会话用“标记包”功能配合“仅显示标记的包”减少渲染压力。6.3 几个被低估的小功能时间显示建议切换成“自参考帧的相对时间”。默认抓包显示的是UTC或本地绝对时间排查接口超时时我需要快速知道两个包之间隔了多久右键“协议首选项 → 列 → 时间”可以加一列Time since previous displayed packet这个相对时间列比绝对时间直观十倍。“着色规则”同样值得自定义。我会给TCP重传配一个深红色的规则给HTTP 5xx响应配橙色给TLS握手配蓝色。这样一打开抓包文件问题区域会自动跳到你眼里。还可以在包列表里用“忽略/不显示”功能把噪声流量临时排除右键报文或过滤器结果后批量忽略剩下的就是干净的目标流量后续分析就不容易分心。还有一个容易被忽略的辅助功能是“包注释”。发现某个可疑包时按CtrlAltC加上注释说明为什么标记它、后续处理结论是什么团队协作时这个笔记能力比共享一个干巴巴的pcap有用得多。我个人在实际操作中还养成了一个习惯抓包文件命名和存档按“日期_现象_抓包位置”来比如“20241031_接口超时_服务端出口”然后分析心得写在包注释里再导出。这样过了半年回查历史问题时根本不用重新回忆当时发生了什么。Wireshark本身的滤波器、分析器、解码器都是公开的真正拉开排障效率差距的其实是你对每一个“为什么”的追问——为什么重传为什么校验报错为什么Wireshark不认识这个协议带着这些问题去翻包、去看图、去写Lua比背一百条过滤器命令都管用。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询