ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Wireshark发送方向数据包长度统计:从包长分布到性能排查实战

Wireshark发送方向数据包长度统计:从包长分布到性能排查实战 Wireshark抓包这件事很多人习惯盯着数据包内容看一个Header一个字节地翻却很少认真对待那个“数据包长度统计”。说实话我之前也这样直到有一次线上故障排查被同事一句“你这抓包里怎么全是60字节的空包”点醒才意识到包长分布这项统计在性能分析里有多好用。今天想把这块经验完整梳理一遍重点讲怎么用它统计“发送方向”的数据包长度包含计量原理、面板操作、命令行方案还有几个我踩过的坑尤其是那个常见的“只能显示520字节”的问题。这个内容适合三类人看第一类是刚入门Wireshark、还停留在用界面看包阶段的新手第二类是网络运维或者后端开发遇到“网络慢、响应卡、带宽被吃满”但不知道从哪下手排查的人第三类是已经会基本过滤和跟踪流但还没系统用过Statistics菜单的进阶选手。1. 为什么关心“发送的数据包长度”从一次故障说起1.1 一次真实的线上问题去年夏天我处理过一起应用响应变慢的事故。后端服务本身CPU、内存都正常数据库也没有慢查询但用户反馈接口时不时卡顿。我分别在客户端和服务端同时抓包Wireshark打开后第一眼没看出什么协议异常TCP没有大量重传也没有RST断开看起来“挺正常”。后来我点了Statistics菜单下的Packet Lengths问题立刻暴露了整个会话里80到159字节的小包占了将近70%而正常业务的大数据包1400字节以上占比不到10%。配合Conversations列表一看发现客户端每隔几十毫秒就在发一批小包像是在疯狂建立短连接或者高频发心跳。顺藤摸瓜查过去才发现是应用层一个定时任务在每次循环里都开了新的HTTP连接而且没有复用导致大量TCP握手包和ACK包把链路占满了。那一次排查真正起决定性作用的就是包长统计这个视图。从那以后我养成了一个习惯拿到一个pcap文件先不看包内容先看长度分布。就像一个医生拿到血常规化验单先看红细胞白细胞计数而不是直接看显微镜下的细胞形态。长度分布虽然不能告诉你包里面具体有什么但它能快速告诉你这条链路上“正在发生什么类型的事”是小包密集的控制流还是大包密集的数据流有没有异常巨型帧有没有大量截断。1.2 发送方向与接收方向必须分开看Wireshark的统计模块默认不做方向区分它会把你捕获到的所有双向包混在一起统计。这在很多场景下会掩盖问题。设想一个场景客户端在向服务器大量上传文件服务器同时也在向客户端推送消息。如果你只看混合的包长分布可能看到60字节小包和1400字节大包各占一半只会觉得“有控制流也有数据流”但根本分不清是哪一端在发小包、哪一端在发大包。实际排查中我们经常需要单独回答“这台主机对外发送的数据包长度分布如何”比如判断某个设备是否在主动扫描网络、某个客户端是否在上传大文件、某个服务是否在向外打大量小包。这种情况下就必须把“发送方向”单独筛出来。方向怎么定义通常有两种理解第一种是IP层方向即源IP是本机、目的IP是对端用ip.src过滤第二种是TCP/UDP端口方向即源端口是本机服务端口用tcp.srcport过滤。具体用哪种取决于你关心的是主机维度还是服务维度。大部分场景下ip.src 本机IP就能准确圈定“从本机发出去”的所有包不论它是TCP、UDP还是ICMP。我在后面的实操里默认都会带上ip.src过滤器这样统计出来的才是“发送数据包”的长度分布而不是混杂了双向流量的整体分布。2. 数据包长度的“度量衡”看懂frame.len和snaplen2.1 Wireshark里的长度字段都表示什么很多新手在Wireshark里点开一条数据包看到好几处带有“Length”字样的字段容易搞混。最常碰到的有三个Frame块里的Length字段IPv4头部里的Total Length字段TCP头部里的Segment Length字段。Frame块里的长度字段完整说其实是两个frame.len表示这个帧在链路上的实际长度以字节为单位也就是“在线上真实跑了多少字节”包括以太网帧头、IP头、TCP头、应用载荷还有底部的FCS校验可能包含的字节frame.cap_len表示实际被Wireshark捕获并保存下来的长度。正常情况下两者一致但如果抓包时设置过snaplen截断cap_len就会小于len。这是后面讲“520字节”问题的关键。IPv4的Total Length是IP层总长度包含IP头本身载荷但不包含以太网帧头和尾部。TCP的Segment Length通常表示这个TCP段承载的载荷字节数不包含TCP头。三条长度之间是层层嵌套的关系以太网帧长度约等于14以太网头 IP Total LengthIP Total Length约等于20IP头 UDP/TCP头 应用载荷。为了直观理解我在下面列几个常见包的典型长度范围包类型以太网帧总长frame.len说明TCP SYN握手包约62字节14以太头20IP头20TCP头8TCP时间戳选项等TCP纯ACK包约60字节类似SYN但选项可能更少整体约60字节空载UDP包DNS查询约60到100字节取决于DNS载荷大小最大标准MTU数据包1518字节1500字节IP报文14字节以太网头不含FCS状态下常见显示1518带VLAN标签的大包1522字节1500字节IP报文4字节VLAN Tag14字节以太网头2.2 为什么抓包显示只有520字节snaplen问题详解见识过真实场景的读者可能遇到过这种情况Wireshark主界面里明明看到一条数据包点进去后数据区后半部分全是灰色或者直接缺失而顶部信息显示“520 bytes on wire, 520 bytes captured”。这里会出现两个长度不一致或者正好都显示520是因为抓包工具在捕获时做了截断只保留了每个包的前520字节。Wireshark在Capture Options对话框里有一个设置叫“Limit each packet to X bytes”这里的X默认是65535。如果这个值被改成了520Wireshark就会对超过520字节的包做截断只保存前520字节。为什么有人会改这个值因为它能显著减小pcap文件的体积。在高流量链路上如果不截断一个抓包文件可能几分钟就上GB把snaplen设成128或256文件能小好几倍。代价就是应用层载荷后半段完全丢失无法做数据重组。但是我个人非常不建议在生产环境抓包时主动调小snaplen除非你明确知道只需要看头部信息。原因很简单一旦截断后续再想做协议分析、文件还原、HTTP body提取全部都会失败。截断数据的时间戳和包长信息还在但载荷缺失会让你错过很多关键证据。至于“怎么显示2090字节的数据”那就简单了把snaplen调回65535重新抓包。如果用的是已保存的截断pcap那没有办法补救只能重新抓因为丢失的载荷不会自己长回来。这个知识点虽然基础但真的是很多人在Wireshark社区反复问的问题我专门在这里写透。2.3 如何正确设置抓包长度避免截断具体操作路径是点击Wireshark主界面的齿轮图标或者直接按CtrlK打开“Capture Options”窗口找到“Capture Filter”区域下方的“Limit each packet to”输入框填入65535。如果是长期设置可以到Edit-Preferences-Capture里修改默认值这样每次新建抓包都会默认采用这个数值。还有一个容易被忽略的点在“Capture Options”里除了snaplen还要留意“Enable promiscuous mode”是否勾选。如果抓包需要关注本机对外发送的所有流量混杂模式通常建议开启否则网卡驱动会过滤掉目标MAC地址不是本机的包导致统计结果缺了一大块。加上现代网卡普遍支持硬件卸载如LRO/GRO抓包时可能会看到超过1518字节的巨型帧这是因为网卡已经把多个TCP段合并成一个大包交给Wireshark了这是正常现象不代表网络真的在发超长帧。这个坑等会儿单独展开讲。3. 实操Packet Lengths统计面板的完整用法3.1 打开Packet Lengths并设置分桶现在假设已经有一个采集好的pcap文件并且确认snaplen是65535没有截断。点击菜单栏的Statistics-Packet Lengths会弹出一个新的统计窗口。界面上方有两个输入框一个是“Interval”用来控制分桶大小另一个是“Ignore packets shorter than”用来过滤掉过小的包。默认的Interval是40意思是从0开始每40字节一个区间直到1518以上。这里的分桶大小很关键设置不同看到的结论会完全不同。如果用默认的40字节一档那么0到39、40到79、80到119这样逐段划分80到159这一档会包含很多TCP控制包因为60字节的ACK、62字节的SYN都在这个区间。如果你关心的是大数据包的分布可以把Interval调大比如200甚至直接选择按2的幂次分桶如果你关心的是小包和正常数据包的边界用40就很合理。窗口下半部分有两块内容左边是表格列出每个长度区间内的包数量、占比、累计包数、累计字节数右边是图形用柱状图直观展示分布。建议看表格时重点看四个指标包数占比、字节数占比、累计包数、累计字节数。占比最直观但字节数占比能告诉你“谁在真正占带宽”。举例来说一个小包区间可能数量占比达到80%但字节数占比只有5%说明链路上虽然包很多但数据量很轻。3.2 只统计发送方向的数据包打开Packet Lengths窗口时它默认会统计当前Wireshark主界面里显示的所有包。如果主界面有显示过滤器生效那么统计窗口会跟随过滤条件只统计过滤后的包。所以想统计“发送方向”的数据包长度最直接的办法是在主界面的显示过滤器栏里输入类似ip.src 192.168.1.100的过滤条件然后再打开Packet Lengths。这里有一个细节需要注意显示过滤器是事后过滤它只会影响统计范围不会影响pcap文件本身。所以即使你过滤了ip.src客户端IP统计结果也只是“从该IP发出的包”完全符合“发送数据包长度”的需求。但如果你的pcap文件非常大几GB级别每次点统计都卡半天那更好的做法是在抓包时就加上捕获过滤器。捕获过滤器的写法是src host 192.168.1.100它在网卡层面就丢弃不相关的包既能减小文件体积也能让后续统计更快。我平时最常用的组合是双保险抓包时用捕获过滤器src host 客户端IP or dst host 客户端IP把与这个IP相关的双向流量完整抓下来分析时再用显示过滤器ip.src 客户端IP单独看发送方向。这样既能保底不遗漏信息又能灵活切换方向。3.3 读出表格里的信息数量、占比、累计拿一次典型的HTTP大文件下载抓包来举例子。客户端向服务器下载一个200MB的文件理论上应该看到大量1518字节左右的以太网帧因为TCP MSS协商后双方都以最大段尺寸发送。如果看Packet Lengths你会发现“1440到1518”这个区间的包数量占比可能超过60%字节数占比甚至超过90%。这说明数据传输非常健康、效率很高。反过来如果看到80到159字节区间的包数量占比很高而1440到1518区间占比很低那就说明链路上“控制包密集、数据包稀少”。这种模式在几种场景下都常见一是DDoS攻击中的TCP SYN Flood或ACK Flood攻击者发大量60字节左右的包二是应用层存在高频心跳或轮询比如某些聊天软件每两秒发一个几十字节的保活包三是TCP没有开启延迟确认导致每收到一个数据段就回一个40到60字节的ACK包。到底属于哪一种可以在包长统计基础上叠加Statistics-Conversations看看这些大流量小包来自哪个IP、哪个端口再进一步跟进去看包内容。另外一个很实用的场景是判断MTU协商是否正常。如果客户端MTU设置成1500但中间链路MTU更小比如PPPoE链路的1492那大包会被分片。在包长统计里如果看到大量1594、1894之类的区间比1518更大说明出现了分片或者网卡开启了巨型帧。这个信息靠肉眼看列表很难发现但长度分布图表上一目了然。4. 进阶用tshark和导出做更细的统计4.1 tshark一行命令完成统计Wireshark的图形化界面方便但有些场景必须在命令行下工作比如在远程服务器上抓包或者要批量处理一堆pcap文件。Wireshark自带的tshark命令行工具可以直接输出Packet Lengths统计效果和图形界面完全一致。最基本的一条命令是tshark -r capture.pcapng -q -z pktlen-r指定读取的抓包文件-q表示安静模式、不逐个打印每包详情-z pktlen表示输出包长统计。加上过滤条件也很方便比如只看某个源IP发送的包tshark -r capture.pcapng -q -z pktlen,ip.src192.168.1.100注意过滤条件是用引号括起来、整体作为-z的参数。输出的表格和图形界面里的Packet Lengths窗口内容一致包含区间、数量、占比、累计等列。批量处理多文件时我一般写个Shell循环对每个文件跑一遍这条命令再把结果重定向到文本文件里一次性对比多个时间段的包长分布非常适合做趋势分析。4.2 按IP/端口拆分发包长度的分布-z pktlen只能给出整体分布如果想知道“每个IP各自发的包长分布”就需要用按会话统计的方式。tshark里和它配合使用的是-z conv,ip它能按IP地址对列出双向会话的包数和字节数但你要的是每个IP单独发送方向的包长分布直接看conv还不够细。更灵活的做法是用tshark导出字段再交给其他工具做聚合。先导出每个包的帧长度、源IP、目的IP、源端口、目的端口tshark -r capture.pcapng -T fields \ -e frame.number -e frame.len -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport \ -E headery -E separator, packets_len.csv导出后就是一个CSV文件每一行是一个包的基础信息。接下来在Excel里做数据透视表行放ip.src列放frame.len的分桶区间值放计数就能一秒看出“哪个源IP在大量发送小包”。这个方法比直接在Wireshark里点统计更灵活也更容易做跨文件对比。4.3 导出CSV后用Excel做透视分析具体在Excel里怎么操作我说一下我的习惯。第一步打开CSV后选中所有列插入一个数据透视表。第二步把ip.src拖到“行”区域把frame.len拖到“列”区域把frame.len或者任意字段再拖到“值”区域改成“计数”。这时候透视表会按源IP和帧长度列出所有组合的包数量。第三步右键frame.len列标签选“组合”设置起始于0、终止于1600、步长150就能得到一个类似Packet Lengths的分桶计数结果。第四步对“计数”列排序看哪些IP的包数最多再针对可疑IP回到Wireshark里单独过滤。这套流程看着多但熟练后处理一个1GB的pcap文件也就是几分钟的事。尤其适合那种“网络感觉慢但说不清哪里慢”的场景先用透视表找到高包量IP、高包量长度区间再缩小范围看具体会话定位效率比漫无目的地翻包高得多。5. 常见问题与排查技巧实录5.1 为什么统计结果全是80~159字节的小包这个问题我遇到不下十次。第一次是在一个无线网络优化项目里客户说带宽被占用严重可实际流量不高。抓包后的Packet Lengths一片红全是80到159字节的区间。后来定位到是设备上的某种网络管理协议在每秒钟广播大量小型报文把无线信道占掉了大半。遇到统计全是小包第一步先看是不是TCP控制包。在Wireshark里加一个显示过滤器tcp.analysis.flags如果统计后命中比例很高说明小包多是重传、重复ACK、零窗口探测这类TCP异常报文根因在网络链路质量或者收发端缓冲区设置。第二步看流量方向如果小包集中来自某一个IP且该IP不是业务服务器就要警惕扫描行为。第三步看协议分布用Statistics-Protocol Hierarchy如果DNS查询或者NTP请求占了很大比例说明是有设备在频繁做域名解析或时间同步。有一种最容易被忽略的情况如果设置了snaplen截断比如只抓前128字节那么所有被抓下来的包在长度列里都会显示128以内无论原始包多大。这时候Packet Lengths看起来也会是“小包一统天下”但这是假象是截断造成的。怎么区分看Frame块的frame.len和frame.cap_len是否相等如果不相等就是截断了先解决抓包设置再说。5.2 TCP分片与长度统计的关系标准以太网MTU是1500字节对应的完整帧长度通常是1518字节。但如果你在Packet Lengths里看到超过1518的区间比如1600、1800甚至更多就需要分情况讨论。第一种情况是网卡开启了巨型帧MTU被调到9000那么正常数据包长度就可能达到9000以上。这种情况在数据中心内部存储网络、NFS、iSCSI环境里很常见。写博文时你只需要知道长度统计里出现超长帧不一定是坏事先确认是不是巨型帧环境。第二种情况是802.1Q VLAN标签。在标准以太网帧里插入4字节的VLAN Tag后帧长度最大可到1522字节。如果交换机配置了QinQ802.1ad还可能出现1526字节的帧。第三种情况是IP分片。当一个大于MTU的IP报文被路由器分片时每个分片本身不会超过MTU所以在标准网络里单条帧长度仍然不会超过1518。但如果你抓包点位于隧道两端比如VXLAN、GRE隧道外层封装会让帧长度显著超过1518。遇到这种情况单纯看包长无法判断是分片还是封装需要配合IP头的Identification字段、More fragments标志位以及协议类型综合判断。检查分片的最快方式是在主界面输入ip.flags.mf 1或者ip.fragments看看有没有分片报文。5.3 “520字节”与“2090字节”一次显示异常排查聊到5.3这个环节我想把标题里那个高频问题完整复盘一遍。有一次论坛上有人发帖说Wireshark里面看到一条数据包长度显示只有520字节但根据应用层协议这个包实际应该有2090字节问为什么Wireshark显示不全。下面回帖众说纷纭有说网卡问题、有说驱动问题、还有人怀疑Wireshark的BUG。实际情况很简单抓包时抓包工具的snaplen被设置成了520。当Wireshark打开这个包时由于数据本身只捕获了520字节它只能显示这520字节的内容后面的载荷区域就是灰的。那2090字节是从哪里来的可能是包列表里显示的长度也可能是协议头里声明了更长载荷但实际捕获数据里根本没有。这个问题要分两层解决。如果原始采集还没有停止赶紧调整抓包配置打开Capture Options把“Limit each packet to”后面的数字改大比如改成65535然后重新抓包。如果pcap已经保存并且停止抓包了那么抱歉截断的数据无法恢复唯一办法是回去重新抓。网上有一些工具声称可以“修复”截断的pcap但严格来说它只能修复文件结构损坏问题无法凭空补出没抓到的载荷字节。很多人不知道的是Wireshark在截断情况下仍然会保留“原始在线长度”和“捕获长度”两个值。打开帧数据展开Frame块能看到“Length: 2090”和“Captured Length: 520”两个字段前者是线上真实长度后者是实际捕获长度。当这两个数值不一样时就说明抓包阶段发生了截断。所以如果你要复现“看到2090字节完整数据”的效果必须确保frame.len和frame.cap_len相等。这个“520”和“2090”的问题本质上是抓包阶段数据完整性的问题。为了避免以后再遇到我的建议是只要条件允许snaplen一律设成65535不要为了省存储空间而牺牲载荷完整性。如果实在担心文件太大可以搭配环形缓冲或抓包自动停止条件而不是靠截断来减小文件。写到这里我还是想多说一句个人体会。我后来每次拿到一个pcap文件基本会先看两个统计一个是Packet Lengths一个是Conversations。前者告诉我链路上是什么类型的流量在跑后者告诉我这些流量到底是哪个IP、哪条连接产生的。两个一交叉大部分“网络有问题但不知道哪里的问题”的排查都能在两分钟内划出一个大概的范围。尤其是发送方向的包长统计配合ip.src过滤后在判断“是不是某台设备在向外打小包、是不是某个客户端在上传大文件、有没有异常的长包扫描”这些场景里真的比单纯翻包要高效得多。最后再分享一个小技巧如果你怀疑抓包文件有截断直接在过滤栏输入frame.len ! frame.cap_len如果有任何包命中说明这个文件中存在截断包需要回头检查抓包时的snaplen设置。
返回列表