ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Wireshark实战笔记:从TCP重传到TLS解密,定位线上故障的抓包方法论

Wireshark实战笔记:从TCP重传到TLS解密,定位线上故障的抓包方法论 抓包这事我到现在都记得第一次把线上问题“破案”的那个晚上。业务监控显示接口P95从50ms飙到2秒日志没有任何报错数据库、中间件指标全部正常。团队盯着监控面板看到凌晨最后是有人提出到网关镜像口拉了一份Wireshark抓包文件打开一看TCP重传包占了将近12%。顺着重传流的源地址一查是其中一台节点网卡光模块故障丢包加乱序应用层被硬生生拖垮了。那之后我就有个很深的体会当所有监控手段都失灵的时候数据包就是最后一层真相。这篇文章不是什么官方文档翻译而是我一線排查这么多年沉淀下来的实战笔记。我会用一条真实的排查思路把Wireshark涉及的几个核心能力串起来讲——抓包前的准备工作、协议交互拆解、几个搜索里高频出现的具体坑以及怎么从一堆看似正常的包里识别出异常流量。适合刚摸到Wireshark想系统掌握抓包实战的人也适合后端、运维、安全方向想要快速定位问题但没有太多抓包经验的朋友。1. 抓包前先做对的几件事决定你后面是不是白忙一场1.1 选对抓包点和网卡比打开工具点开始更重要很多人打开Wireshark就直接双击网卡点开始抓了一堆包然后发现目标流量根本没进去。这不是工具的问题是抓包点没选对。先理清一条逻辑流量到底是从哪里经过的如果是本机发出的请求和响应比如调试本地程序、排查API调用直接选本机网卡就行数据包会经过回环接口Loopback。Windows上装了Npcap默认就支持回环但偶尔会有驱动开关没打开的情况需要在Npcap安装时勾选“Support loopback traffic”否则你在Wireshark里怎么都看不到127.0.0.1的包。如果是排查两台机器之间的通信最忌讳的就是随便找台机器抓包。比如A和B之间有交互问题你在C机器上打开Wireshark就算开了混杂模式也抓不到A和B的流量——普通交换机只会把流量发给目标端口不会发给所有端口混杂模式只能保证本网卡把收到的包都传给抓包工具并不能让交换机把不该给你的包给你。真正要抓A和B之间的流量应该在接入层交换机上做端口镜像或者上层的流量镜像口把A、B两个端口的流量复制一份到抓包端口。我自己的习惯是开始抓包之前先ping一下目标地址确认三层可达然后在捕获过滤器里加上host限定把范围缩小到具体IP。这样可以避免抓包文件被无关流量撑大解析效率也会高很多。还有一个小细节抓包时长比较久或者流量大的时候记得在Capture Options里把Buffer大小从默认的2MB往上调同时设置自动停止条件比如“抓满50MB自动停止”或者“持续5分钟停止”免得把机器磁盘写满了。1.2 两个过滤器别搞混这决定了你的包“能不能看”Wireshark里有一对特别容易混淆的概念捕获过滤器和显示过滤器。它们名字像作用完全不同混用的人我见了不止一次。捕获过滤器在网卡驱动层面生效底层是BPF语法意思是从源头就只保留匹配的包没匹配到的直接丢不进Wireshark。它的好处是省磁盘、省内存坏处是语法和显示过滤器不一样写错了直接报语法错误。比如host 192.168.1.10 and tcp port 443这是BPF语法意思是只抓源或目的IP为192.168.1.10且TCP端口为443的包。显示过滤器是Wireshark把包都抓下来之后在上层做筛选只是让不符合条件的包“不显示”包仍然在文件里。它的语法是面向协议字段的比如ip.addr 192.168.1.10 tcp.port 443如果你把显示过滤器写法填到捕获过滤器框里比如输入ip.addr 1.1.1.1大概率会得到“Syntax error”的红色提示因为BPF看不懂这种字段表达式。反过来如果你在显示过滤器里填BPF语法比如host 1.1.1.1它也不会按你的预期去过滤显示过滤器里根本没有host这个关键字。所以在动手之前先问自己一句我是要把流量提前扔掉还是只在屏幕上筛选前者用捕获过滤器后者用显示过滤器。实际工作中百分之八十的场景用显示过滤器就够了因为它更灵活随时可以改条件重新看包。捕获过滤器更常用于“流量实在太大不提前扔掉机器吃不消”的场景。2. 一个HTTP案例把协议拆解的思路彻底搞清楚2.1 从三次握手到HTTP报文逐层读包的正确姿势协议拆解听起来很高大上说白了就是回答一个问题这个包到底在干什么Wireshark已经把每一层的头部字段帮你解析好了你只需要知道按什么顺序看。我随便用一个访问网页的场景举例。打开Wireshark设置好显示过滤器http然后刷新一个页面。Packet List面板里会依次出现TCP握手包和HTTP请求响应包。最开始那三个包一定长这样第一包是SYN第二包是SYN, ACK第三包是ACK这是TCP三次握手建立连接的过程。点中第一个包看Packet Details面板你会看到一个像洋葱一样的层级结构Frame物理层信息包含帧长度、到达时间、捕获时的时间戳。Ethernet II数据链路层核心字段是源MAC、目的MAC、上层协议类型0x0800表示IPv4。Internet Protocol Version 4网络层核心字段是源IP、目的IP、TTL、协议号6表示TCP。Transmission Control Protocol传输层核心字段是源端口、目的端口、序列号、确认号、Flags标志位。Hypertext Transfer Protocol应用层这时候才看到真正的HTTP方法、URI、状态码。这套层级体系不是随便排的它对应了TCP/IP协议栈的封装关系——应用层数据往下传每层加一个头部到了接收端再一层层揭开。抓包阅读方向就是“从下往上”先看以太网帧确定收发设备再看IP确定主机再看端口确定应用最后看载荷确定业务内容。如果你右键一个HTTP请求包选“Follow → HTTP Stream”就能看到一整条HTTP流里完整的请求和响应内容。这个功能非常实用排查“某个接口到底返回了什么”的时候比在Packet List里一包一包翻高效得多。但要注意一个坑如果服务端开启了gzip或br压缩Follow界面里看到的中文可能是一堆乱码这不是抓包的问题是Wireshark没有自动解压HTTP body。这种情况下可以先用响应头的Content-Encoding确认压缩方式再决定是否需要手动解压。2.2 问题不在HTTP层多半在TCP层RTT、乱序和重传怎么看真正让业务变慢的地方很多时候不在HTTP层而在TCP层。HTTP本身只是一个文本协议它把请求发给TCP后就等着响应TCP层一旦开始重传、乱序应用层感知到的就是延时暴涨。以一次“接口慢”的排查为例。显示过滤器限定ip.addr 目标IP然后看Packet List里的Time列。Wireshark默认显示的是相对时间戳左侧数据包列表也可以加一列Time since previous frame in TCP stream用于看同一个TCP流里相邻包的间隔。你会发现包与包之间出现了异常的间隙比如某个包之后停顿了200ms紧接着就出现了一个TCP Retransmission标记。出现重传本质是发送端在规定时间内没收到ACK于是重新发了一遍。Wireshark有一个专门的视图辅助判断Statistics → TCP Stream Graph → Time-Sequence(Stevens)。横轴是时间纵轴是序列号正常情况下这个图应该是一条平滑向上的斜线代表数据按序发送并被确认。一旦图上出现平台期、回落、锯齿状突刺几乎可以断定TCP层在反复重传或乱序。这里面还有一个很容易踩的坑看到TCP层出现大量分片或者MSS异常第一时间怀疑MTU。Wireshark里每个TCP包都有一个TCP Segment Len字段这个字段不会超过通信双方在三次握手里协商的MSS。如果你发现某个大响应被拆成了很多个Segment Len接近MSS的TCP包注意看它们是否按顺序到达。如果顺序颠倒大概率是中间设备做了负载均衡导致包走了不同路径或者是网卡TSO卸载功能开了导致抓包视角看起来像“大包分片”这个我在后一节专门展开。3. 热搜里的高频坑逐个拆开讲3.1 为什么抓包只能看到520字节怎么才能看到2090字节这个坑在搜索里出现频率极高抓一个应用层数据Wireshark明明抓到了但Packet Details里每个包只有520字节左右实际想看的2000多字节数据怎么都看不到。遇到这个问题不要急着怪Wireshark分两层去排查。第一层先看抓包时的Snaplen是不是被限制了。Capture Options里有一个“Limit each packet to”选项默认值是262144字节正常情况下不会截断。但如果你或者其他人之前手动改成了512、256之类的数值那抓进来的每个包就只保留前N字节后续内容直接被丢弃。这种情况下重新抓包时把该选项调回默认值即可。第二层如果Snaplen没问题那八成是网卡TSO/GRO/GSO卸载功能导致的。这里的原理需要稍微解释一下现代网卡支持“大包卸载”应用层一次性把2090字节的数据交给协议栈协议栈利用TSOTCP Segmentation Offload把这些数据直接下发给网卡由网卡硬件自己切成MSS大小的TCP段再发出去。也就是说在以太网线缆上传输的实际是多个1514字节的帧每个TCP段的Payload大小约为1460或者更低。在Wireshark的视角里你看到的自然就是一个520字节的TCP分段而不是最开始那个2090字节的应用层大包。想确认是不是TSO导致有个简单办法看同一流的相邻TCP包序列号是否在连续递进且Payload长度都接近MSS。如果是基本就是TSO的分段结果数据并没有丢只是被网卡“拆开”了。在Linux上临时关了再抓包命令是ethtool -K eth0 tso off gro off gso offWindows上则在网卡属性的高级选项卡里找到“大量发送卸载IPv4”和“大量接收卸载”设置为Disabled。关掉之后重新抓包你会看到应用层的大包恢复原样。这里有个注意点关闭卸载功能会增大CPU占用生产环境慎用排查完记得恢复。至于最多看到的520字节还有一个可能场景是TLS记录层边界。TLS加密流量在TCP流里每发一段密文会先加一个记录头记录长度通常不会超过16KB如果开启了TLS 1.3或者特定的分段策略单条记录可能就几百字节看起来和“数据被截断”的直觉很接近。但这类情况只要看到TLS层能正常解析出Record Layer就知道不是丢数据。3.2 筛选UDP前后两包的时间间隔别再用肉眼数了UDP没有像TCP那样的序列号和确认机制很多人觉得调试UDP无从下手尤其是“两个请求之间隔了多久”这种问题靠肉眼在Packet List一行行找效率低还容易看错。Wireshark里其实已经把时间间隔算好了。Packet List的列头默认显示的是Time一列但你可以自己加一个更精确的列。方法右键Packet List的任意列头选择“Column Preferences”弹出窗口后点左下角的加号新建一列在Fields这一栏填上frame.time_delta标题随便写比如“Delta”类型选“Custom”。这个字段的含义是当前包与上一次显示的包之间的时间间隔。加完列之后配合显示过滤器可以非常灵活地找出异常包。比如你想看哪些UDP包距离上一包超过了1秒udp frame.time_delta 1如果你想看的是同一个UDP流的首包和尾包间隔靠显示过滤器做不到得用命令行。tshark是Wireshark自带的命令行工具一行就能把时间间隔导出来tshark -r capture.pcap -Y udp -T fields -e frame.time_delta -e ip.src -e ip.dst -e udp.srcport -e udp.dstport输出的每一行就是UDP包之间的时间差和五元组信息拿到Excel或者配合awk排序很快就能找出“哪个会话的哪两个包之间出现了异常大间隔”。这个方法我常用在排查游戏UDP同步卡顿、DNS解析慢的场景比盯着图形界面一目了然得多。3.3 TLS解密调试HTTPS接口的最后一公里HTTPS流量抓下来默认是密文Packet Details里只能看到TLS握手和Application Data密文没法直接看HTTP请求体和响应体。要解决这个问题需要让浏览器或者应用程序把TLS密钥导出给Wireshark。具体操作分三步。第一步让浏览器导出密钥。Windows和macOS下先配置环境变量SSLKEYLOGFILE指向一个本地文件路径比如D:\sslkeys\keys.log然后重启浏览器。第二步打开Wireshark选择“编辑 → 首选项 → Protocols → TLS”找到“(Pre)-Master-Secret log filename”填上同一个文件路径。第三步重新开始抓包访问HTTPS站点你会发现Wireshark能直接解析出HTTP层的内容了。加密通信的过程简单说就是客户端和服务端先通过非对称加密协商出一个对称加密密钥之后所有业务数据都用这个对称密钥加密传输。SSLKEYLOGFILE记录的就是这个协商过程的密钥材料Wireshark拿到它之后就能在内存中实时解密后续的密文数据相当于给调试人员留了一把备用钥匙。这里提醒一句密钥文件等同于加密流量内容的访问权限别随便发给别人调试完就删。另外企业级App可能会做证书绑定或者禁止加载系统证书Wireshark自带的解密对这类场景不一定有效那就需要从应用进程自己导出密钥或者用HOOK类方案复杂度会高很多。4. 异常流量识别从“看着正常”到“看出问题”4.1 用Expert Info快速定位TCP重传、乱序和丢包Wireshark左下角有一个黄色圆形图标名字叫“Expert Info”很多人从来没点开过。这个功能相当于Wireshark内置的“体检医生”它已经把包里的异常情况按严重程度分好了级别Error错误、Warning警告、Note提示。点开Expert Info你会看到类似下面的条目级别说明常见含义Error严重协议错误序列号跳变、校验和失败、畸形包Warning传输质量问题TCP重传、重复ACK、乱序、上一分段丢失Note一般性提示首个包不是SYN、可疑的连接重定向其中Warning级别的Previous segment lost和Retransmission要重点看。Previous segment lost意思是当前包的序列号出现了断层Wireshark推断中间有包没到Retransmission表示某个序列号的数据被重新发送了。这两个现象叠加基本就是网络上真实存在丢包。想要量化重传率可以用显示过滤器数一下重传包数量再除以总包数。重传包过滤器tcp.analysis.retransmission在一个正常的局域网环境里TCP重传率通常在0.1%以下。如果超过1%说明链路质量已经有问题了到5%以上业务层大概率能感知到卡顿。这里注意一个细节无线Wi-Fi环境的重传率天然比有线要高一些判断异常时要用同一类环境的基线做对比不要拿无线去套有线的标准。4.2 广播风暴、ARP异常和扫描行为的识别思路异常流量不一定都是重传这种“看得见的病”有些是“慢性的”比如局域网里的广播风暴它会让你觉得网络越来越慢但抓包看单个协议又没什么大毛病。广播风暴的特征是广播包和组播包大量涌出占据网络带宽。在Wireshark里最快的判断方式是看Statistics → Protocol Hierarchy观察ARP协议或者其他广播类协议在所有包里的占比。一个正常的以太网里ARP流量占比非常低。如果ARP占比突然升高到10%、20%甚至更高说明有人在疯狂发ARP请求——可能是某个设备的ARP表反复被清空也可能是有设备网卡异常在持续广播。ARP请求本身是一个“谁有某个IP地址请告诉我你的MAC地址”的广播查询。正常局域网里偶尔出现几次是完全正常的但异常情况下会出现一个源MAC在极短时间内发出大量目的IP连续递增的ARP请求这种模式可以用显示过滤器筛出来arp.opcode 1 eth.src xx:xx:xx:xx:xx:xx然后看Target IP列是否呈连续扫描趋势。同样如果发现同一个源IP在短时间内向多个目标端口发TCP SYN请求而又没有对应的ACK响应这也是一种典型的异常探测行为可以配合Statistics → Endpoints看哪些节点对外连接数异常突出。识别出源后优先检查是否中了病毒木马或者配置了错误的服务探测任务而不是一上来就定性为攻击——实操中很多“异常”其实是内部工具误配置导致的。4.3 用IO Graph和Conversations建立“正常基线”的概念识别异常的本质是偏离基线。如果你平时看惯了某个环境的“正常包长什么样”异常出现时一眼就能发现不对劲。对于还没建立这种感觉的人我建议多用Statistics → IO Graph和Statistics → Conversations。IO Graph是一个时间维度的流量图。打开之后可以看到不同协议的流量随时间变化的曲线。正常情况下一个业务系统的流量曲线应该是白天高、深夜低或者和业务活动时间高度相关起伏比较平滑。异常情况下曲线会有明显的尖峰或者周期性脉冲。比如每5分钟出现一次几秒钟的高流量尖峰很可能就是定时任务在进行大量数据迁移全天候不断的小脉冲则可能是心跳包或探活机制异常。Conversations则是一个会话维度的统计面板会列出所有参与通信的地址对以及每个会话的字节数。我拿到一份陌生抓包文件时第一件事就是打开Conversations按Bytes排序看看哪个IP对会话流量最大。通常流量最大的会话就是业务的主体流量如果发现某个完全陌生的IP组合占据了大量流量就需要重点检查是不是有数据外传或者爬虫在抓取接口。这三个功能组合起来就形成了一条完整的流量分析路径先用Protocol Hierarchy看协议占比再用IO Graph看时间趋势最后用Conversations落到具体会话。三步走完一份pcap文件基本能讲出百分之八十的故事。5. 从抓包文件到结论我常用的几条tshark自动化经验5.1 为什么命令行比图形界面更高效Wireshark图形界面用来交互式分析很顺手但当你需要批量分析几十个pcap文件或者要从抓包文件里提取特定字段做统计时再一个个点界面就太慢了。这时候tshark的价值就体现出来了。tshark是Wireshark自带的命令行工具功能几乎覆盖了图形界面的所有能力。常用的几个命令先看文件的基本统计信息快速了解流量规模和协议分布tshark -r capture.pcap -q -z io,stat:0提取HTTP请求的URI列表排查接口占用情况tshark -r capture.pcap -Y http.request -T fields -e http.request.method -e http.host -e http.request.uri统计DNS查询次数最多的域名tshark -r capture.pcap -Y dns.flags.response 0 -T fields -e dns.qry.name | sort | uniq -c | sort -rn | head -20这几条命令单个看并不复杂但组合起来就形成了一个很顺手的分析工作流。特别是当你需要向别人汇报排查结论的时候命令行输出的csv格式可以直接扔进表格里做排序和图表比截图清晰多了。5.2 批量分析pcap一个实际脚本的思路有一次我拿到一批从不同节点镜像口导出的pcap文件大概二十来个每个几百MB。任务是要统计所有节点里TCP重传率最高的文件再定位重传集中的时间段。手工一个个打开Wireshark显然不现实最后用了一个简单的bash循环加tshark组合for f in *.pcap; do total$(tshark -r $f -Y tcp -T fields -e tcp.seq 2/dev/null | wc -l) retrans$(tshark -r $f -Y tcp.analysis.retransmission 2/dev/null | wc -l) echo $f,total$total,retrans$retrans done然后挑出重传数最高的文件再用IO Graph确认时间点。整个过程十分钟内完成。Python配合pyshark也能做同样的事但这里要提醒一个坑老的pyshark版本依赖Python2和一些过时的库在全新环境里经常装不上而且pyshark底层调用tshark的方式有时候会漏掉部分显示过滤器字段。我的个人建议是大多数分析场景直接用tshark就够了先把tshark的-T fields用熟比引入大量依赖更省心。如果你的环境是Python3pyshark 3.x可以正常使用但注意pyshark读取大文件时内存增长很快分析几百MB以上的文件时还是要谨慎。命令行用的顺了以后会发现抓包分析不再只是一次性救火行为而是可以沉淀成一套每天自动运行的检测脚本把异常重传、异常会话、异常协议占比这些指标推送到监控面板里真正做到“把问题消灭在用户感知之前”。抓包这几年给我的最大感受是Wireshark不是只有网络工程师才需要掌握的工具后端开发排查接口超时、运维定位链路抖动、安全同学分析可疑样本都绕不开它。每一次抓包都是在跟协议栈的客观事实对话应用层可以撒谎日志可以遗漏但数据包永远在那里。学会把问题翻译成过滤器语言再用统计视图把零散的数据包拼成完整的画面这套思路才是抓包真正的价值所在。
返回列表