尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

网络分层与抓包分析:用Wireshark和Scapy快速定位故障层

网络分层与抓包分析:用Wireshark和Scapy快速定位故障层 简介《网络传输过程及各层次分析》是一份面向计算机网络初学者、需要系统梳理网络分层知识的讲解型文档以数据封装与传递为主线完整覆盖OSI七层模型和TCP/IP四层协议栈。文档从应用层HTTP、传输层TCP/UDP、网络层IP到数据链路层ARP与物理层信号传输逐层解析各层职责与代表性协议并结合QQ发送消息的实例生动展示数据从应用层到物理层再被对方接收的完整路径。同时文档专门对比了交换机、路由器、集线器三类设备交换机负责数据帧交换路由器负责数据包路由集线器仅做物理信号转发帮助读者分清容易混淆的概念。资源为单个docx文件大小约54KB内容包含层次结构图、跨网段ARP解析过程以及局域网络由转发说明既适合课程学习与期末复习也可作为网络基础面试前的速查材料。目前已有325人学习下载读者可借此快速掌握网络传输过程的整体框架和各层次协作机制。1. 网络传输过程与层次分析先想清楚“卡在哪一层”再动手“页面打不开、视频卡在缓冲、远程连接反复断开”这些问题报过来的时候我们习惯先问一句卡在哪一层这句话背后的思维方式就是对网络传输过程做层次分析。网络从物理线路到应用交互中间隔了好几层协议栈每一层都在干活也都可能拖后腿。这篇文章围绕网络传输的层次分析展开把OSI/TCP-IP的分层逻辑、Wireshark抓包里的分层特征、以及一套能落地的层次分析脚本讲清楚。适合正在接触真实网络问题的运维工程师、后端开发以及刚上手抓包分析的人。读完后你至少能回答三个问题每个包在每一层做了什么、出问题时该看哪个字段、以及怎么把一堆抓包数据变成“某一层有问题”的结论。2. 把OSI和TCP-IP的每一层拉到数据包上分层模型与Wireshark对应关系很多人背得出七层模型但真到打开Wireshark那一刻就蒙了满屏的MAC地址、IP地址、端口号、TCP标志位到底哪一段对应哪一层其实抓包窗口就是分层模型的“实拍照片”你看到的每一个字段都有明确所属层。理解这层对应关系是后面做任何统计、排查和自动化的地基。2.1 五层模型与抓包视图每一层在Wireshark里长什么样实际工作中很少有人真的按七层去排查因为会话层和表示层在TCP-IP体系里被应用层吸收了。我们日常讲“从下往上排”用的是五层模型。为了让你在抓包窗口里能快速认出每一层我把它们整理成一张对应表层级典型协议抓包里的辨认特征常见问题信号物理层以太网、Wi-Fi没有独立字段只能从接口统计看信号弱、大量CRC错误数据链路层Ethernet源/目的MAC地址、帧类型0x0800为IPv4重复帧、帧校验失败网络层IP、ICMP源/目的IP地址、TTL、协议号、分片偏移TTL超时、分片丢失传输层TCP、UDP源/目的端口、序号、确认号、窗口大小、标志位重传、乱序、窗口缩零应用层HTTP、DNS、TLSWireshark的“显示协议”列会直接显示协议名慢响应、4xx/5xx、TLS握手超时这张表解决的是“看到字段不知道属于谁”的问题。Wireshark在“Packet Details”面板里已经按层级折叠好了每展开一行左侧文件区就高亮对应的那一段字节。比如你点开“Transmission Control Protocol”这一行下面的端口号、Seq、Ack、Flags全属于传输层不用去翻协议文档。2.2 分层头部字段拆解这些字段各管什么事以一次最常见的TCP访问为例一个数据包从外到里依次是以太网帧头、IP头、TCP头、应用数据。每个头部里都有几个排障时必看的字段。以太网头只有三个字段值得关心目的MAC、源MAC、帧类型。前两个决定这个帧从哪个物理口送出去帧类型决定上层交给谁解析。排障时如果看到目的MAC是FF-FF-FF-FF-FF-FF说明这是一个广播帧常见于ARP请求如果广播帧占比异常升高要考虑局域网内是否有环路或者扫描行为。IP头的关键字段是TTL、协议号和分片偏移。TTL每经过一个路由器减1看到TTL明显小于常见初始值Windows是128、Linux是64说明路径很长或者有环路。协议号标识上层协议6是TCP、17是UDP、1是ICMP。分片偏移不为0时说明这个包已经被中间设备拆过配合DF标志能判断MTU问题。TCP头是重灾区。源端口和目的端口告诉你“谁在访问谁”Seq和Ack序号是TCP保证有序传输的核心任何异常都会体现为乱序和重传窗口大小是接收方通告给发送方的剩余缓冲空间看到窗口缩成0说明接收方处理不过来。TCP标志位里的SYN、ACK、FIN、RST直接对应连接建立、确认、关闭和异常断开。Wireshark用不同颜色标出了TCP同步包和异常包如RST第一眼就该看这些。2.3 为什么“分层位置”决定排障方向Ping通但业务不通的案例排障时最容易犯的错是“凭感觉查”。一个局域网里的设备互相Ping得通但打开文件共享服务就是超时。Ping通说明物理层、链路层、网络层都是通的ICMP回包能回来至少三层没问题。但文件共享走的是TCP端口如果防火墙策略只放了ICMP没放对应端口的TCP流量四层就会卡住。这时候你在Wireshark里看访问方发出去的TCP SYN包有没有SYN-ACK回包一目了然没有回包就是中间策略问题有回包但最后一直重传就是链路丢包或者对端处理不过来。所以排障的正确顺序永远是先“定层”再“定因”。先看问题出在二层广播、三层路由、四层端口还是七层业务逻辑。层没定准后面所有的分析都是在瞎折腾。这个思路贯穿整个抓包分析过程也是后续脚本设计的基本逻辑。3. 用Scapy写一个分层统计脚本抓包、按协议归类、算占比Wireshark自带“统计”菜单能看协议分层但那是对单个文件做的交互式分析。如果你想每周对线上pcap自动做一次分层统计或者想针对某个时间窗口单独计算各层数据占比还是写脚本更靠谱。这里我用Scapy来跑原因是它读取pcap之后能用一个数据包对象把各层协议穿起来比直接用文本解析高效得多。3.1 最小可用的分层统计脚本读取pcap并按协议栈归类先装依赖一条命令的事pip install scapy然后准备一个抓包文件。如果你手头没有pcap可以用tcpdump临时抓一小段tcpdump -i eth0 -c 5000 -w sample.pcap注意抓包时长取决于你的流量大小不要在业务高峰抓太久几百MB的文件后面处理起来很慢。下面是读取pcap并按五层模型归类的脚本from scapy.all import rdpcap from collections import defaultdict def classify_packet(pkt): 把单个数据包解析成 [链路层, 网络层, 传输层, 应用层] 的协议列表 layers [] # 数据链路层以太网帧 if pkt.haslayer(Ether): layers.append(Ethernet) # 网络层IPv4 或 IPv6 if pkt.haslayer(IP): layers.append(IPv4) elif pkt.haslayer(IPv6): layers.append(IPv6) # 传输层TCP / UDP / ICMP 按需识别 if pkt.haslayer(TCP): layers.append(TCP) elif pkt.haslayer(UDP): layers.append(UDP) if pkt.haslayer(ICMP): layers.append(ICMP) # 应用层这里只抽象标记是否有上层载荷 if len(layers) 3 and pkt[layers[2]].payload: app_name _guess_app_layer(pkt) layers.append(app_name) return layers def _guess_app_layer(pkt): 简单按端口猜应用层协议生产环境建议结合协议特征 sport pkt.sport if hasattr(pkt, sport) else 0 dport pkt.dport if hasattr(pkt, dport) else 0 if 80 in (sport, dport): return HTTP if 443 in (sport, dport): return HTTPS/TLS if 53 in (sport, dport): return DNS return Other def layered_stats(pcap_file): pkts rdpcap(pcap_file) layer_counter defaultdict(lambda: [0, 0]) # 层名 - [包数, 字节数] for pkt in pkts: layers classify_packet(pkt) layer_name | .join(layers) layer_counter[layer_name][0] 1 layer_counter[layer_name][1] len(pkt) return layer_counter if __name__ __main__: stats layered_stats(sample.pcap) total_pkts sum(v[0] for v in stats.values()) for layer, (cnt, bytes_cnt) in sorted(stats.items(), keylambda x: -x[1][1]): print(f{layer:30s} 包数 {cnt:8d} 占比 {cnt/total_pkts*100:5.2f}% 字节 {bytes_cnt})这段代码的核心逻辑是读入pcap后对每个包按“以太网→IP→TCP/UDP→应用层”的顺序逐层判断把命中的协议名拼成一个链路标签再按这个标签累加包数和字节数。最终输出的是“数据包协议栈路径”的统计表比如Ethernet | IPv4 | TCP | HTTPS/TLS这一行就代表一条完整的TLS加密访问会话数据。_guess_app_layer用端口猜测应用层协议这只是简化做法实际生产环境里HTTP也可能跑在8080端口上最好再检查payload特征。代码里有几个参数可以按需调整pcap_file是输入文件路径total_pkts的计算方式决定了占比的分母是全部包数如果你只想统计某一个IP或端口的数据可以在读取时用filter参数先做BPF过滤。另外rdpcap是一次性把整个文件读入内存处理几百MB的文件时会占用大量内存这种情况建议改成PcapReader以迭代方式逐包读取from scapy.all import PcapReader with PcapReader(big_file.pcap) as reader: for pkt in reader: # 逐包处理逻辑对比一下就知道rdpcap适合小文件和交互式分析PcapReader适合脚本化定时任务处理大文件时不至于把服务器的内存吃光。在写定时采集脚本时建议直接放弃rdpcap统一用迭代器。3.2 统计各层数据量与占比把“层次分析”做成可量化的表格跑完上面的脚本你会得到类似下面的输出Ethernet | IPv4 | TCP | HTTPS/TLS 包数 3000 占比 60.00% 字节 2400000 Ethernet | IPv4 | TCP | HTTP 包数 1000 占比 20.00% 字节 800000 Ethernet | IPv4 | UDP | DNS 包数 500 占比 10.00% 字节 50000 Ethernet | IPv4 | ICMP 包数 300 占比 6.00% 字节 18000 Ethernet | IPv6 | UDP | Other 包数 200 占比 4.00% 字节 12000这个表格就是一次最简单的“层次分析”结果。怎么解读如果TLS流量占比最高说明业务加密流量占主流这类包无法直接看传输内容排障重心要放在TCP层看握手时延、重传率、窗口大小。如果DNS流量占比异常高比如每秒几千个DNS请求那要么是终端中毒在做域名探测要么是应用层没有做DNS缓存。如果ICMP占比突然飙升优先怀疑路径上有设备在做连通性探测或者网络出现了环路。字节数这个指标同样关键。有些层包数少但字节数大比如视频流走UDP传输包不多但每个包都是大包有些层包数多但字节数很小比如TCP ACK包每次只有几十字节。当你要评估“流量到底用在哪里”时包数和字节数必须分开看。这也是“层次分析”里一个容易被忽略的维度单纯看包占比会高估ACK包的影响单纯看字节占比又会低估控制协议的影响。3.3 参数怎么调BPF过滤、时间窗口和pcapng兼容用脚本做分层统计时最容易忽略的是“统计口径”。同样一个pcap文件过滤条件不同结论可能完全相反。先说BPF过滤。如果你只想统计某个来源IP的流量在rdpcap里加filterpkts rdpcap(sample.pcap, filtersrc host 192.168.1.10)这样可以节省内存也让输出结果更聚焦。但注意BPF过滤发生在抓包层的“读入”阶段一旦过滤掉某个方向的流量后续分析就再也找不回来。所以我的习惯是先全量读入统计完再做业务维度的二次切片而不是一上来就加过滤条件。时间窗口也是常见需求。线上文件可能是连续抓了好几个小时的但问题只发生在业务高峰那十分钟。脚本里加一个按时间过滤的逻辑from datetime import datetime from scapy.all import PcapReader start datetime(2024, 6, 1, 10, 0, 0).timestamp() end datetime(2024, 6, 1, 10, 10, 0).timestamp() with PcapReader(sample.pcap) as reader: for pkt in reader: t float(pkt.time) if start t end: # 只统计这个时间窗内的包 pass这里pkt.time是Unix时间戳直接和datetime转换好的边界比较就行。要注意抓包文件里包序可能和实际发送序不完全一致时间过滤之后可以再加一个按TCP序号的排序避免乱序包干扰延迟统计。4. 各层性能参数与故障特征慢请求来了先盯哪一层分层统计只能告诉你流量长什么样解决不了“为什么慢”。慢请求的排查思路是把一次完整交互按层拆成若干段分别测量每一段消耗的时间哪一段异常就锁定哪一层。这一套方法和第2章的分层模型是配套的只不过从“看字段”变成了“看延迟和重传”。4.1 各层必盯的参数表谁出问题谁背锅以下是我在实际排查中会关注的核心参数和经验参考值不是协议规范里的标准但作为健康基线足够用层级关键参数健康参考值异常说明物理层/链路层CRC错误帧、重传帧率低于0.01%网线、光模块、交换机端口故障网络层ICMP丢包率、RTT、TTL变化内网RTT5ms丢包率0.1%丢包集中在中段链路TTL递减异常为环路网络层分片率接近0MTU配置不一致大包被拆分传输层TCP重传率小于0.1%丢包、拥塞、对端处理能力不足传输层零窗口次数出现即异常接收方应用处理不过来背压传输层乱序率小于0.1%多路径传输、链路负载不均应用层TTFB首字节时间内网50ms公网300ms服务器处理慢、DNS解析慢应用层TLS握手时长一次握手100ms证书链过长、加密协商过慢这张表的核心价值是给“正常”定义一个基线。没有基线就谈不了异常判断。每个网络环境都不一样拿到一张新拓扑时我会先连续抓24小时正常业务流量跑一遍这些指标存成基线数据后续再有告警拿当前数据和基线对比而不是去套教科书上的数值。4.2 典型故障链路一TCP重传居高不下怎么办现象很直观Wireshark里大量黑色或红色的TCP重传包文件传输速度上不去应用表现为“偶尔卡住几秒”。首先确认重传发生在哪个方向。如果是客户端发出去的包被重传说明客户端到对端的反向路径上有丢包如果是服务器回包重传则问题可能在接收方向。用Wireshark打开抓包文件找到一次重传包点击“分析→追踪TCP流”能看到这个连接的全部时序。重点看两点第一重传之前丢的那个原始包是不是真的没有再出现过第二重传间隔是呈指数增长每次翻倍还是固定间隔。指数增长是标准超时重传说明中间链路存在稳定丢包固定间隔重传且伴随多个乱序包更可能是链路负载均衡导致包走了不同路径。这种场景我会先做两件事一是用ping带大包压一下中间链路ping -c 100 -s 1400 目标IP看平均丢包率和最大RTT二是检查两端设备的TCP参数尤其是发送缓冲区是否太小。很多情况下业务流量本身并不大但发送缓冲区设置过低导致TCP窗口频繁受限数据发不出去最终表现为重传而不是丢包。4.3 典型故障链路二HTTP请求慢但Ping完全正常这是最让人头疼的一类问题Ping延迟只有1ms但浏览器打开页面要几十秒。这种情况要把一次HTTP请求拆成四段来测DNS解析时间、TCP握手时间、TLS握手时间、业务响应时间。Wireshark里按http过滤定位到那一次请求然后用“统计→流量图”选择“TCP流”视图能直观看到每条连接的时间轴。DNS慢在Wireshark里看dns.time列超过100ms就要考虑更换本地DNS或检查上游DNS递归性能。TCP握手慢从SYN发出到SYN-ACK回来的间隔大于10ms内网环境就重点看中间设备有没有做TCP代理或ACL策略。TLS握手慢客户端发出ClientHello到服务器返回ServerHello的间隔过大通常是对端服务器性能或证书链太长。业务响应慢TTFB之后到整个内容下载完成前耗时很大说明应用本身处理慢和网络无关。这一套拆法就是把“应用卡顿”这个黑匣子按层次切开来。实际操作时逐个时间点打标记然后分别取差值不要凭感觉判断。这样查出来的结论不仅准确还能直接做成自动监控指标。5. 分层分析避坑指南5个让方案翻车的边界问题分层分析看着简单真正上手做一次就会发现到处是坑。以下五条都是我自己踩过的或者帮别人排查时见过的高频问题按“现象→原因→解决”写清楚希望能帮你少走几趟弯路。5.1 抓包抓不到任何数据或只看到一片空白包现象Wireshark已经选择了一个网卡并点了开始但列表里始终不出现任何包。或者能抓到包但全是长度小于64字节的空包解析不出IP和端口。原因最常见的两类。一是本机有多块网卡实际业务走的接口不是默认显示的那个比如虚拟机里的NAT网络出口和物理网卡里看到的根本不是同一个接口。二是抓的是本机环回口127.0.0.1的流量Windows的Npcap默认不带环回接口抓包Linux下则需要在tcpdump里显式指定-i lo。解决先执行ipconfigWindows或ip addrLinux确认当前业务接口的名字抓包时指定该接口。Windows下需要抓环回流量时重新安装Npcap并勾选“Support loopback traffic”Wireshark里就会出现Loopback: lo接口。抓包前再确认抓包权限Linux下tcpdump需要root权限普通用户会直接提示权限不足。5.2 大量TCP校验和错误但网络明明没问题现象Wireshark里看到大量包被标记为“TCP checksum incorrect”数量可能占所有TCP包的百分之几十但业务一切正常没有任何丢包重传。原因现代网卡都支持checksum offload功能网卡硬件在发送前才计算校验和并写入包头。抓包工具拿到的是操作系统内存里的原始数据包此时校验和字段还是占位的0于是被误判为错误。这是一个典型的“抓包本身改变了数据形态”的例子。解决不要在Wireshark里对这些包做校验和判断。进入“视图→首选项→协议→TCP”取消勾选“Validate checksums if possible”。这样显示层面就不会再标红。同时要清楚一点校验和错误显示的包实际在链路上未必有问题真正需要关注的是网卡驱动统计里的RX errors。5.3 小包Ping通大包Ping不通业务时好时坏现象ping 目标IP默认大小32字节完全正常但加上-s 1400后立刻出现丢包或延迟暴涨。业务表现为上传大文件反复失败小文件正常。原因这是典型的MTU不一致。两端的接口MTU一致但中间某一跳的MTU更小大包超过中间设备的承载上限又被设置了DF标志不能分片只能被丢弃。应用层TCP一般能通过PMTUD自动探测但UDP业务或者被防火墙过滤掉ICMP消息后就无法自动降包长。解决逐跳探测MTU。Windows下用ping -f -l 1400 目标IPLinux下用ping -M do -s 1400 目标IP。从1400开始逐步加大找到恰好无法通行的临界值再减去IP和ICMP头一共28字节就是实际可用MTU。然后在两端网络设备或操作系统上统一调整MTU不建议只改一端。顺带把ICMP不可达消息放行否则PMTUD会一直失败。5.4 同一网络里延迟忽高忽低分析回放却找不到原因现象线上监控显示访问某个业务的RTT大部分时间在5ms左右但每个几分钟就会跳到200ms抓包回放时在这个时间窗口里没看到重传也没看到明显的拥塞信号。原因延迟抖动并不总是由IP网络引起交换机或安全设备上的流量整形、限速策略以及无线环境里的干扰和信道竞争都会产生周期性延迟尖峰。更隐蔽的是服务器端的业务线程池打满请求在服务器队列里排队但抓包点在客户端看到的是“响应端到端延迟拉长”这个延迟其实是服务器应用处理的排队时间。解决把抓包点放到两个位置同时抓一处在客户端一处在服务器接入交换机镜像口。两边用同一个NTP源对齐时间戳。如果客户端侧看到请求发出后长时间没有ACK问题在中间链路如果SYN-ACK及时返回、但服务器侧抓包显示HTTP响应延迟大问题在服务器应用层。时间戳对不齐也是坑尽量用带纳秒精度的pcapng格式同时用clock_gettime打标。5.5 DNS缓存污染或hosts文件错误导致排查方向完全跑偏现象抓包显示HTTP请求收发正常TCP没有重传应用层请求也返回了但页面就是显示错误或跳转到奇怪的页面。原因客户端本地DNS缓存或hosts文件里存在错误的记录请求根本没发到业务服务器而是被解析到了一个错误IP。这类问题从网络层看完全正常因为网络传输过程的每一层都正常执行了错的只是目标地址本身。解决第一时间在Wireshark的“会话视图”里看TCP连接的目的IP再和业务方的域名预期解析结果比对。确认被误导后在客户端执行nslookup 域名看实际解析结果检查系统hosts文件里有没有残留记录。抓包前先做一次这个动作能避免后面白看几百兆流量。6. 用层次分析法把抓包结论变成决策数据R语言算权重与贡献率前面做的分层统计和故障排查解决的是“某一层有没有问题”。但管理者经常问的是另一个问题多条优化方案同时能改善网络体验先投哪一个这时可以用层次分析方法把网络质量拆成多个准则算每个准则对最终体验的贡献率让决策有数可依。6.1 建立网络质量评估的层次结构把“网络传输质量”作为目标层下面设准则层我一般取四个指标延迟、丢包率、重传率、带宽利用率。最下层是方案层对应实际可执行的优化动作比如调整MTU、优化无线部署、扩容带宽、增加缓存节点。构造这个结构的目的是把“网络体验差”这个模糊问题拆成几个可以独立量化的指标然后靠判断矩阵给出权重。6.2 用R语言构造判断矩阵、做一致性检验并计算权重判断矩阵是层次分析方法的核心输入元素含义是“指标i相对指标j的重要性”。R语言里的实现很直接# 构造准则层判断矩阵延迟、丢包率、重传率、带宽利用率 # 数值来自对业务诉求的判断1表示同等重要3表示稍重要5表示明显重要 M - matrix(c( 1, 3, 4, 5, 1/3, 1, 2, 3, 1/4, 1/2, 1, 2, 1/5, 1/3, 1/2, 1 ), nrow 4, byrow TRUE) colnames(M) - rownames(M) - c(延迟, 丢包率, 重传率, 带宽利用率) # 计算最大特征值对应的特征向量归一化后作为权重 eig - eigen(M) lambda_max - Re(eig$values[1]) w - Re(eig$vectors[, 1]) w - w / sum(w) names(w) - rownames(M) # 一致性检验 n - nrow(M) CI - (lambda_max - n) / (n - 1) RI - 0.89 # n4时查表得到的平均随机一致性指标 CR - CI / RI cat(权重贡献率:\n) print(sort(w, decreasing TRUE)) cat(sprintf(CR %.3f%s\n, CR, ifelse(CR 0.1, 通过一致性检验, 未通过请调整判断矩阵)))这段代码的输出里权重就是每个指标对目标的贡献率。比如计算结果是“丢包率 0.52、延迟 0.27、重传率 0.13、带宽利用率 0.08”说明这个业务里丢包是体验的最大决定因素优先要做的是链路质量优化而不是扩容带宽。注意RI0.89是4阶矩阵的常用取值不同资料里略有差异但只要CR小于0.1结论就稳定。6.3 让权重和抓包实测数据互相验证层次分析方法有个天然局限判断矩阵来自主观经验必须拿真实数据校验。把第3章脚本跑出来的丢包率、重传率、延迟、带宽利用率对照算出的权重做一个简单排序。如果权重最高的是丢包率但实测里丢包率只有0.01%而延迟已经50ms了说明当时的判断矩阵存在偏差需要重新调整判断矩阵里的标度值。我现在的习惯是先用脚本算出实测各层“贡献率”再用层次分析方法给出优化优先级两边交叉验证。这样给领导讲方案时既有抓包数据做证据又有权重模型做决策依据落地推进的阻力会小很多。希望帮到你。本文还有配套的精品资源点击获取
返回列表