找回密码
立即注册
搜索
发回帖 发新帖

6187

积分

0

好友

782

主题
发表于 昨天 23:56 | 查看: 3| 回复: 0

用户反馈连接慢,应用说没收到请求,可网络监控却显示链路一切正常。这类场景下,抓包的价值在于把“连接到底发生了什么”变成一条可观察的时序线。TCP 握手是否完成、数据是否到达、确认是否返回、谁发出了重置,这些都能从合适位置的报文中找到线索。但抓包同样容易制造误判:采集点丢包会看起来像网络丢包,网卡卸载会像校验和错误,中途才开始采集则会把正常数据标记成异常。

本文采用虚构教学链路:客户端 192.0.2.10 访问服务器 192.0.2.20:443,抓包文件统一称为 incident.pcapng。文档中的地址需要替换为真实且已获授权分析的端点。所有命令与过滤器都是写作示例,并未宣称在读者链路上实测。Wireshark 图形界面用于交互查看,TShark 用于离线导出,dumpcap 或 tcpdump 用于采集。字段名称与可用偏好设置应以现场版本查询结果为准。

抓包内容可能包含业务正文、认证数据和内部拓扑,采集前应限定接口、端点、时长与保存位置。分析可以读取报文,不意味着可以随意分享整个文件。本文不要求关闭安全机制、修改生产 TCP 参数或人为注入故障;涉及实验的部分会明确标记。分析的主线是先验证采集质量,再找连接,再读序号和时间,最后把报文证据与主机、代理、应用日志关联起来。

抓得对,比抓得多更重要

列出可采集接口,能避免选中没有业务流量的网卡。图形界面通常也会显示接口流量曲线,但在容器、多网卡和隧道场景下,仍然应该核对实际出口。下面用 TShark 读取接口清单,不开始采集。若没有权限,应按发行版方式配置抓包权限,而不是让整套图形界面以 root 长期运行——采集程序与分析程序可以分开使用。

tshark -D

查看目标的路由决策,有助于确定主机上哪个接口能观察出站流量。结果不保证回程经过相同接口,也不说明代理后端连接使用相同五元组。下面查询文档服务器地址,现场应替换。存在负载均衡、NAT 或容器桥时,要画清客户端到入口、入口到后端两段连接,不能只在其中一段寻找另一段的序号。

ip route get 192.0.2.20

带时间限制的采集可以控制文件规模,端点与端口过滤可以减少无关数据。下面只在已确认接口采集一分钟,并保存为 pcapng。若故障发生在连接建立之前,过滤条件必须包括握手两端,而不能只保留应用正文。采集结束后要保存标准错误中的统计信息,特别是内核丢弃数量;没有这些信息,后续重传判断就缺少质量依据。

sudo dumpcap -i eth0 -f 'host 192.0.2.20 and tcp port 443' -a duration:60 -w incident.pcapng

无法预测故障何时发生时,可以用循环文件保存最近窗口。这里每个文件约 100 MB,保留五个,具体计量单位按工具手册解释。循环采集会覆盖最早文件,发现事故后应尽快停止或复制保留相关窗口。磁盘写入能力也要满足捕获速度,不能把循环配置当作不会丢包的保证;繁忙主机还应观察采集开销。

sudo dumpcap -i eth0 -f 'tcp port 443' -b filesize:100000 -b files:5 -w ring.pcapng

截取长度决定每个报文保存多少字节。只分析 TCP 头时可以减少长度,但 TLS、HTTP 和重组分析可能需要完整负载。下面示例保存完整报文,适用于已授权的短时采集。数据最小化不是一律截断,而是根据问题选择信息;若长度太短,后面看不到应用内容时不能宣称应用没有发送,只能说采集没有保留。

sudo tcpdump -ni eth0 -s 0 -c 10000 -w incident.pcap 'host 192.0.2.20 and tcp port 443'

抓包过滤器使用 libpcap 语法,显示过滤器使用 Wireshark 字段语法,二者不能互换。下面是一条只捕获特定双端点 TCP 流量的采集过滤器,可填入采集设置。它在报文进入文件之前过滤,因此被排除的流量无法后续找回。过滤过窄可能遗漏 DNS、ICMP 或另一个后端端口;故障范围尚未清楚时应先确保关键上下文。

host 192.0.2.10 and host 192.0.2.20 and tcp

显示过滤器只改变当前分析视图,不会删除原文件里的其他报文。下面用字段表达同样的端点条件,但实际语法与上一条不同。对包含多协议的文件,先按端点缩小再观察连接数量,能够减少被无关异常提示干扰。对 IPv6 应使用相应字段,不能以 IPv4 字段过滤后看不到数据就认定整个采集为空。

ip.addr == 192.0.2.10 && ip.addr == 192.0.2.20 && tcp

文件元信息能说明采集时间、封装格式、报文数量和平均速率。下面在分析之前查看,确认文件覆盖了事故时间。平均速率不能代表瞬时峰值,也不能证明没有丢包;它只是文件层面的概览。多个采集点合并后还可能有不同接口时间戳和重复报文,需要保留原始文件身份,避免把合并后的统计当作单一链路事实。

capinfos incident.pcapng

两端采集需要时钟可比较,否则毫秒级差异可能来自时间偏移。下面读取主机时间同步状态,命令取决于现场服务。同步正常也不保证微秒级准确,因此比较两端包到达时间时要说明误差范围。序号、确认号与负载长度通常比绝对时间更适合关联同一个 TCP 段,时间只在已确认精度条件下用于定位延迟。

timedatectl status
chronyc tracking

先找完整连接,再读握手中的角色与序号

TCP 会话统计能快速找到持续时间长、数据量大或报文数量异常的连接。下面离线读取文件,不生成新流量。统计包含整个文件里的会话,某个连接的起点可能早于采集窗口。选择分析对象时要结合业务请求时间与端口,不能仅按最大流量排序就认定它是问题连接——大量正常下载也会排在前面。

tshark -r incident.pcapng -q -z conv,tcp

握手第一步通常是客户端发送 SYN,ACK 标志未设置。下面过滤初始请求,便于统计谁在主动连接。SYN 也可能重发,过滤结果数量不等于独立连接数量,需要结合五元组和初始序号。抓包从中途开始时可能完全看不到 SYN,这时应说明连接起点不可见,而不是判断它未经过正常握手。

tcp.flags.syn == 1 && tcp.flags.ack == 0

服务器回应通常同时设置 SYN 和 ACK,用确认号承认客户端的初始序号。下面筛选这类响应。SYN 会占用一个序号空间,因此确认号不是简单等于客户端序号。看到响应后还需要查看客户端是否返回最终确认,以及报文是否到达正确客户端;只在服务端看到 SYN-ACK 发出,不能证明客户端已经收到。

tcp.flags.syn == 1 && tcp.flags.ack == 1

握手最终 ACK 不携带 SYN,但它与大量普通确认报文具有相同标志形态。下面只是握手所在流中的候选过滤,必须通过序号和前后时序识别。不要把所有 ACK 都叫第三次握手,也不能以 ACK 数量计算连接建立次数。TCP 还可能在最终确认中携带数据,分析时应允许这种行为,而不是要求它必须是零负载报文。

tcp.stream == 0 && tcp.flags.ack == 1 && tcp.flags.syn == 0

Wireshark 为文件内每条连接分配流编号,方便把双向报文集中查看。下面选择编号零,实际编号应从目标报文的字段获取。流编号是分析文件内部标识,换文件、合并文件或改变解析环境后不一定相同。跨采集点关联应使用端点、端口、时间与序号,不能要求两份文件的同一连接都具有相同 stream 编号。

tcp.stream == 0

导出握手关键字段,能把图形界面观察整理为时序表。下面包括相对时间、地址、端口、标志、序号、确认号与负载长度。相对序号的显示取决于解析偏好,比较两份文件时应确认是否一致。表里缺失的字段可能来自协议不匹配或解析条件,不应把空字段当成数值零直接计算。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -T fields -e frame.number -e frame.time_relative -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e tcp.flags -e tcp.seq -e tcp.ack -e tcp.len

原始序号便于跨抓包点核对同一段,不受相对编号显示的影响。下面导出原始序号与原始确认号,再结合长度关联。TCP 序号会回绕,长连接和大流量分析需要按照协议空间解释,不能简单把整数差当作累计字节。五元组相同也可能在不同时间被重新使用,因此关联还要包括连接生命周期和初始序号。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -T fields -e frame.time_epoch -e tcp.seq_raw -e tcp.ack_raw -e tcp.len

下面是虚构握手时序,用于解释相对序号。客户端和服务器 SYN 各消耗一个序号,最终确认应承认对端下一个期望序号。真实协议选项、时间戳和重发可能让列表更复杂。这个简化表只说明序号关系,不能用它推断所有网络的握手延迟;生产中应测量实际时间并说明抓包位置。

0.000000 client -> server SYN       seq=0
0.012000 server -> client SYN,ACK   seq=0 ack=1
0.024000 client -> server ACK       seq=1 ack=1

只有 SYN 重发而没有响应时,问题可能在请求路径、服务监听、返回路径或采集点。下面筛出某个流的 SYN,观察间隔和重复序号。客户端重发间隔往往受内核策略影响,但不能仅凭固定秒数认定某设备丢包。需要在服务端确认是否看到请求,以及是否发出响应,才能把无响应拆成更具体的故障分支。

tcp.stream == 0 && tcp.flags.syn == 1

重传标记是线索,序号和确认关系才是核心证据

普通重传标记说明分析器认为某段可能再次发送。它来自状态与时序推断,不是网络设备直接报告的丢包原因。下面用于定位候选,再逐条核对之前同序号范围和之后确认。采集丢包、中途采集和重复镜像都可能改变判断。结论应写成“观察到重发行为”或“工具标记候选”,不要直接扩大为“交换机一定丢包”。

tcp.analysis.retransmission

快速重传通常与重复确认或其他丢失信号相关,恢复动作可能比重传超时更早发生。下面筛选分析器的快速重传标记,仍需观察之前双向报文。不同拥塞控制和恢复算法的行为并不完全相同,不能要求每次快速重传都严格出现同样的三条重复 ACK。报文证据应与端点内核实现和是否启用 SACK 一起解释。

tcp.analysis.fast_retransmission

重复 ACK 表示接收端再次确认某个累计序号,可能提示某段未到,也可能反映重排、窗口变化或采集上下文问题。下面选择候选报文,注意确认号是否不变、是否携带 SACK,以及窗口字段如何变化。重复 ACK 数量不能直接换算成丢失报文数量,更不能把一个双向连接里的所有确认统计混在一起判断。

tcp.analysis.duplicate_ack

乱序标记说明当前段的到达顺序与分析器预期不符。它可能来自网络重排,也可能来自多接口采集排序或重复镜像。下面定位候选后,应检查缺口是否很快补齐以及是否产生实际重传。轻微乱序可能被端点正常处理而不影响业务,诊断应关注恢复成本与持续性,不能把任何乱序标记都视为需要修改网络配置。

tcp.analysis.out_of_order

丢失段标记意味着分析器看到序号缺口,并不证明该段在网络里确实丢失。若抓包点自己丢包,接收端可能已经收到完整数据。下面的候选需要与 ACK 是否跨过缺口、采集丢弃统计以及另一端文件比较。发现 ACK 已确认缺失区间时,优先考虑采集漏包或路径不完整,避免把分析文件缺口直接当作业务传输缺口。

tcp.analysis.lost_segment

伪重传标记常意味着段被再次发送时,分析器已经观察到对该范围的确认。可能存在确认丢失、时间关系问题或镜像重复,不能只看标签猜测。下面把候选放回整个流检查,特别关注反向 ACK 到达发送端的证据。一个采集点看到了 ACK,并不保证发送端也看到,所以两端观察可以帮助区分真实重复发送与采集假象。

tcp.analysis.spurious_retransmission

重传分析应保留双向流,不能先删除 ACK 再运行诊断。下面输出候选报文关键字段,便于回到原文件查看。字段缺失应保持为空,序号范围以负载长度计算,SYN 和 FIN 另占序号空间。比较时不要只对单个序号去重,因为分段方式可能改变,同一字节范围可能以不同长度重新发送。

tshark -r incident.pcapng -Y 'tcp.stream == 0 && (tcp.analysis.retransmission || tcp.analysis.fast_retransmission)' -T fields -e frame.number -e frame.time_relative -e ip.src -e tcp.seq_raw -e tcp.len -e tcp.ack_raw

SACK 允许接收端报告已经收到的非连续区间,使发送端更有针对性地恢复缺口。下面筛选存在 SACK 区间的报文,结合累计确认号理解哪一段仍未确认。SACK 是接收端观察,不是对网络设备的故障定位。若某个区间在后面补齐并快速恢复,业务影响可能较小;大量持续缺口则需要进一步检查路径与端点压力。

tcp.options.sack_le || tcp.options.sack_re

对一个指定原始序号范围定位,可以核对首次发送与后续重发的覆盖关系。下面用教学数值作为筛选条件,真实值从目标段获得。区间交集需要考虑段起点与长度,简单相等筛选可能漏掉不同分段的重发。长流中还要注意序号回绕,这个简化过滤适用于确认没有跨越回绕边界的小窗口分析。

tcp.stream == 0 && tcp.seq_raw >= 100000 && tcp.seq_raw < 102000

连接重置要分清发包方向、生命周期和中间设备

RST 标志表示连接被重置,但不直接告诉你为什么。下面找全部重置报文,再核对来源方向、序号有效性与当时连接状态。端点、代理、防火墙和其他设备都可能生成或转发重置。报文源地址看起来是服务器,也不保证一定由服务器应用触发;现场需要结合双端采集、TTL、主机日志和代理日志判断来源。

tcp.flags.reset == 1

按服务器方向筛选重置,可以快速观察它发生在 SYN 后、请求数据后还是长时间空闲后。下面只选教学服务器,后端存在代理时应分别分析两段连接。握手之前的拒绝与传输中途的断开属于不同分支,不能用同一句“服务端主动断开”解释所有 RST。记录相邻数据与确认时序,才有依据关联服务监听或应用异常。

ip.src == 192.0.2.20 && tcp.flags.reset == 1

客户端也可能因为超时、取消请求或进程退出发送重置。下面筛选客户端方向,避免所有错误都被归因于服务端。客户端 SDK 的超时与重试设置会影响这些行为,抓包需要与调用方日志关联。看到客户端 RST 后服务端写入失败,服务端错误可能是结果而非起因;排障应沿时间顺序寻找最早出现的异常。

ip.src == 192.0.2.10 && tcp.flags.reset == 1

导出重置前后的时间和序号,可以形成可审阅的断连记录。下面只导出 RST 行,完整上下文仍保留在原文件中。单行没有应用请求是否完整的信息,也无法说明对端已处理多少数据。诊断记录应附流编号和相邻报文范围,方便其他人复核,避免一张重置截图被当成整个故障过程。

tshark -r incident.pcapng -Y 'tcp.flags.reset == 1' -T fields -e frame.number -e frame.time_relative -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e tcp.seq_raw -e tcp.ack_raw

SYN 后立即收到 RST,常见于没有监听或策略明确拒绝,但必须核对端点实际服务状态。下面在已授权服务器读取监听套接字,确认地址族、绑定地址与端口。服务只绑定回环或只监听 IPv6 时,外部 IPv4 连接可能无法被接受。监听存在也不排除中间设备拒绝,主机状态只是定位链的一部分。

sudo ss -lntp 'sport = :443'

传输中途重置需要检查应用错误与进程生命周期。下面读取教学服务在事故时间段的日志,时间应替换并与抓包时钟校准。进程崩溃、协议解析失败、连接池回收或请求取消都可能关联。日志中没有记录也不能证明应用无关,某些异常不会完整落日志;可以进一步查进程退出、代理错误和系统资源信息。

journalctl -u app.service --since '2026-09-30 10:00:00' --until '2026-09-30 10:10:00' --no-pager

FIN 表示正常关闭方向上的发送结束,与 RST 的语义不同。下面筛选 FIN 后查看双方确认和另一方向剩余数据。TCP 支持半关闭,一端不再发送并不要求对端立即停止发送。所谓四次挥手也可能因 ACK 与 FIN 合并而表现为更少报文,不能用固定报文数量认定正常关闭缺失。

tcp.flags.fin == 1

空闲连接被回收后,客户端复用它时可能看到重置。下面筛出一个流并显示时间差,帮助发现长间隔。时间差大只是线索,需要与连接池、代理和 NAT 的空闲超时比较。修改客户端连接池回收策略可能比扩大所有中间设备超时更合适,尤其是链路多层代理时,最小超时边界需要统一认识。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -T fields -e frame.number -e frame.time_relative -e frame.time_delta_displayed -e tcp.flags -e tcp.len

TTL 和其他头部特征可以辅助比较重置与正常服务端报文是否来自相似路径,但不是可靠身份认证。下面导出同一流的 TTL、IP 标识与标志。NAT、负载均衡、多路径和不同主机栈都可能改变这些特征。不能仅凭 TTL 不同就断言防火墙伪造 RST,应把它当作推动双端采集与设备日志调查的线索。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -T fields -e frame.number -e ip.src -e ip.ttl -e ip.id -e tcp.flags

窗口、往返时间和吞吐,解释为什么没有重传也会慢

TCP 接收窗口表示接收端当前愿意接收的范围,与发送端拥塞窗口不是同一个量。下面筛出零窗口标记,常提示接收端暂时无法继续接收数据。应用不及时读取、内存压力和处理停顿都可能导致这种现象。扩链路带宽不一定有效,应先确定窗口由哪一端收缩,以及它是否与业务处理停顿一致。

tcp.analysis.zero_window

零窗口探测让发送端检查接收窗口是否重新开放,不应被当成普通应用负载或无意义重传。下面定位探测报文,观察后续窗口更新。探测间隔受端点实现影响,单凭其频率无法判断链路故障。若窗口长期关闭,应检查接收端读取速度与资源;若很快恢复,则需要量化停顿对请求完成时间的影响。

tcp.analysis.zero_window_probe

窗口更新说明接收端调整了可接受容量。下面筛选分析标记,结合缩放后的窗口大小观察恢复。窗口缩放通常在握手协商,抓包没包含握手时分析器可能无法完整解释窗口数值。对此应说明上下文不足,不能拿原始窗口字段直接计算最大吞吐;保留握手是性能抓包的重要要求之一。

tcp.analysis.window_update

窗口满标记提示发送的数据接近接收端公布边界,可能解释发送停顿。下面筛选候选后,与接收窗口、ACK 和应用读写情况一起检查。一个标记不代表整个连接都受窗口限制,更不等于服务器 CPU 一定不足。真正的性能结论需要观察多个窗口周期和业务负载,避免由单个报文推断长期瓶颈。

tcp.analysis.window_full

导出窗口原始值、缩放因子和计算值,可以检查解析是否具备协商信息。下面只针对目标流。字段在部分报文上可能为空,这是上下文与字段适用范围导致,不应统一补零。比较不同抓包文件时要记录是否使用同样解析偏好,以及是否有完整握手,否则窗口曲线的差异可能来自分析条件而非端点行为。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -T fields -e frame.time_relative -e ip.src -e tcp.window_size_value -e tcp.window_size_scalefactor -e tcp.window_size

ACK RTT 是分析器把确认与已观察发送关联后的时间差,受抓包位置、延迟确认和重传等因素影响。下面导出存在 RTT 的报文,用于观察趋势。它不等于应用响应时间,也不一定等于整条网络最纯粹的传播时延。出现高值时应核对确认策略与数据发送时间,不能把所有高 RTT 都解释为某一段网络排队。

tshark -r incident.pcapng -Y 'tcp.analysis.ack_rtt' -T fields -e frame.time_relative -e tcp.stream -e tcp.analysis.ack_rtt

带宽时延积说明高速长距离链路需要足够在途数据才能利用带宽。下面使用 1 Gbit/s 和 40 ms RTT 的教学数值,计算约 5 MB 的理论在途量。真实吞吐还受拥塞控制、窗口、丢包、应用速度和协议开销影响。这个计算用于理解为何小窗口可能限制吞吐,不是建议直接修改内核缓冲区到同一个固定值。

bandwidth_bps=1_000_000_000
rtt_seconds=0.040
bdp_bytes=bandwidth_bps*rtt_seconds/8
print({'BDP_bytes':bdp_bytes,'BDP_MiB':bdp_bytes/1024**2})

按时间窗口统计报文和字节,可把慢请求与流量变化关联。下面使用一秒窗口,输出是文件内流量统计,不等于应用有效吞吐。重传字节、协议头和无关连接都会影响总量。若要评价某个下载,需要先明确流和方向,再按 TCP 有效负载与去重序号范围计算,不能把整个接口包速率称为业务吞吐。

tshark -r incident.pcapng -q -z io,stat,1

已建立连接的内核状态可以补充抓包看不到的端点信息,例如部分 TCP 统计。下面在事故现场读取对应目标连接,工具输出随内核版本变化。主机状态是采样时刻的快照,不一定与之前文件时间对应。把它与抓包一起保存,能帮助识别发送受限、接收缓冲和重传计数,但仍需要根据字段语义解释。

ss -ti dst 192.0.2.20

排除采集假象,再把问题扩大到网络设备

网卡分段与聚合卸载会让主机抓包里的报文大小不同于线缆上的实际帧。下面读取卸载能力与当前状态,不修改。大 TCP 段在发送主机上可能尚未分段,接收主机上也可能已被聚合。看到超过接口 MTU 的采集包不能直接认定网络发送了超大帧,应先明确采集位置与卸载处理阶段。

sudo ethtool -k eth0

校验和卸载可能让本机发送报文在抓包时显示校验和未完成,线上实际报文却正确。下面筛选解析器判断不良的 TCP 校验和状态,字段取值应由版本文档确认。是否真正错误需要在接收端或外部采集点复核。不要因为主机抓包出现大量提示就关闭所有卸载,修改网卡特性可能显著增加 CPU 并影响业务。

tcp.checksum.status == 0

原始报文长度大于保存长度说明采集发生了截断,后续应用层解析可能不完整。下面定位截断包,用于解释为什么流重组缺少正文。截断与网络丢包不同,前者是文件没有保存全部字节。若分析目标需要完整负载,应重新设计合法采集;无法重新采集时必须在结论中注明,不得凭缺失正文推断发送端没有数据。

frame.cap_len < frame.len

采集进程和网卡计数提供不同层面的丢包线索。下面读取接口统计并记录短窗口 CPU 情况,工具是否安装取决于发行版。采集结束时的 dropped 统计也要保存。网卡丢包、内核捕获缓冲丢包和网络中间设备丢包是不同问题,只有把这些层次分开,才能解释文件里的序号缺口究竟来自哪里。

ip -s link show dev eth0
pidstat -u -C dumpcap 1 5

在 any 接口或多个镜像口采集时,同一个逻辑报文可能出现多次。下面导出接口编号与端点,帮助检查重复来源。时间戳接近且头部几乎相同只是线索,不应直接去重所有相似 TCP 段,因为真实重传也可能相似。分析应保留接口信息与原始文件,先识别采集拓扑,再决定是否建立去重视图。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -T fields -e frame.number -e frame.interface_id -e frame.time_epoch -e tcp.seq_raw -e tcp.len

两端文件可以合并查看,但合并不会自动修正时钟、NAT 地址或重复报文。下面生成新文件而保留原件,便于回到单端观察。合并后同一段可能出现两份,分析器重传标记也可能受到影响。因此跨点比较应先建立端点与时间映射,并优先用原始序号核对;合并视图只能辅助时序展示,不能替代采集条件说明。

mergecap -w combined.pcapng client.pcapng server.pcapng

按事故时间截取文件有利于减少分析规模,但窗口必须覆盖连接上下文。下面使用明确的教学时间范围,工具解析的时间应与本机时区确认。截得过窄会丢失握手或最初的缺口,导致后续窗口与重传分析不完整。新文件只作为工作副本,原文件要保留,必要时可以回看更早的报文解释连接状态。

editcap -A '2026-09-30 10:00:00' -B '2026-09-30 10:05:00' incident.pcapng window.pcapng

保存目标流时,显示过滤器可作用于离线文件写出。下面保留双向完整流,不只保存异常包。只有异常包的文件会破坏分析器上下文,也让其他人无法复核正常过程。流文件仍可能含敏感数据,分享前应按问题最小范围审阅;删掉某些负载字节可能破坏解析,脱敏方案要保留必要协议结构并说明处理方式。

tshark -r incident.pcapng -Y 'tcp.stream == 0' -w selected-stream.pcapng

IP 分片也可能影响应用层重组,特别是路径 MTU 与隧道场景。下面筛选 IPv4 分片相关报文,注意并非所有文件都会出现。TCP 通常依靠分段避免 IP 分片,但配置、隧道与其他协议仍可能导致分片。发现分片后要检查是否所有片段都可见,不能把重组失败直接归因于 TCP 重传机制。

ip.flags.mf == 1 || ip.frag_offset > 0

连接建立成功以后,还要区分 TLS 与应用等待

DNS 查询失败会让 TCP 连接根本没有开始。下面先筛 DNS,观察查询、响应和返回码。加密 DNS 或代理解析可能不出现在当前文件里,不能因为没有 DNS 包就说客户端没有解析。需要根据客户端实际解析方式选择采集点。排障按 DNS、连接、TLS 与应用逐层推进,可以避免在没有连接的情况下反复找 TCP 重传。

dns

TLS 握手发生在 TCP 之上,TCP 成功并不意味着安全连接建立成功。下面筛 ClientHello 与 ServerHello,观察协议协商是否有响应。TLS 版本、加密握手以及解析支持会影响可见字段。没有应用解密材料时,仍可分析握手和记录时序,但不能宣称已经看到加密正文中的业务请求内容。

tls.handshake.type == 1 || tls.handshake.type == 2

TLS 告警可能解释 TCP 已建立却很快关闭的情况。下面筛选可见告警记录,具体描述是否可解析取决于协议阶段和加密。证书问题、协议不匹配与应用策略可能触发不同告警。需要与客户端错误和服务端 TLS 日志对应,不能把所有告警都叫证书过期,也不能因为后面出现 RST 就跳过最早的 TLS 失败。

tls.alert_message

明文 HTTP 的请求与响应可以直接筛选,适合教学或合法内部测试。下面只筛协议对象,不用于证明 HTTPS 正文已经可见。代理把 TLS 解密后转发明文时,抓包位置决定能观察到哪层协议。分析报告应明确采集位于客户端、TLS 终止点还是后端,避免把后端 HTTP 状态解释成客户端看到的完整响应。

http.request || http.response

导出明文 HTTP 响应状态和关联时间,可以把 TCP 层与应用层区别开。字段在重组完成的帧上出现,不一定对应第一段响应字节。下面使用两遍分析以补充需要后续知识的关联字段,只适用于可回读的离线文件。时间还可能包括服务处理与网络等待,不应仅凭一个值把问题定位到数据库或应用 CPU。

tshark -2 -r incident.pcapng -Y 'http.response' -T fields -e frame.number -e tcp.stream -e http.response.code -e http.time

跟随 TCP 流有助于查看双向字节内容,下面输出十六进制视图,适用于已授权数据。它不是自动解密工具,也不保留所有报文头时序。加密流会呈现不可直接阅读的字节,这是协议设计而非抓包失败。分享输出之前应检查是否包含凭据、Cookie 或业务正文,不要把完整流复制进公开故障文章。

tshark -r incident.pcapng -q -z follow,tcp,hex,0

应用数据已经被 TCP 确认,只表示对端协议栈接收了相应字节,不表示应用已经成功处理或持久化。下面筛纯确认候选,方便观察确认进展。累积确认可能承认多个段,不能一条 ACK 对一条请求简单配对。请求超时但数据已确认时,应继续检查应用层响应、代理排队与服务处理,而不是把 ACK 当成业务成功证明。

tcp.stream == 0 && tcp.len == 0 && tcp.flags.ack == 1 && tcp.flags.syn == 0 && tcp.flags.fin == 0 && tcp.flags.reset == 0

HTTP/2 和其他多路复用协议在同一 TCP 连接承载多个请求,TCP 流编号不是请求编号。下面筛 HTTP/2 协议对象,是否能解析取决于明文或合法解密条件。一个流中出现延迟不能直接归属于某个请求,需要进一步按应用流标识关联。TCP 丢失会影响共享连接上的多个请求,但实际影响取决于协议与实现,分析要保留层次区分。

http2

HTTP/3 使用 QUIC 与 UDP,不能用 TCP 握手过滤解释它。下面筛 QUIC 或常见 UDP 端口,只作为识别候选,并不假定所有该端口流量都是 QUIC。客户端可能从一种协议回退到另一种,抓包应同时包含相关端点和协议。发现没有 TCP 流时,要先确认客户端实际协议,而不是立即判断服务没有收到连接。

quic || udp.port == 443

形成可复核的统计,而不是统计所有红色提示

协议层级统计能确认文件包含哪些协议及大致占比。下面读取文件概览,结果受采集过滤和解析影响。占比高不等于故障概率高,解析失败也可能由截断或非标准端口导致。它适合作为分析起点,后续还要按事故流和时间窗口查看;对整个文件运行一次专家信息就发布结论,容易被无关连接与采集假象干扰。

tshark -r incident.pcapng -q -z io,phs

专家信息汇总可快速列出解析器认为值得关注的现象。下面只做初筛,工具等级与颜色不代表业务严重度。严重级提示也可能来自不完整采集,普通提示则可能对应真正影响请求的窗口停顿。分析应把候选逐条放回连接上下文,并说明哪些已经证实、哪些仍需补充证据,避免用工具措辞替代自己的诊断。

tshark -r incident.pcapng -q -z expert

统计重传候选时,要明确是否合并多个标记、是否排除采集重复以及分母是什么。下面统计目标流的不同候选类型行数,不宣称它是网络丢包率。一个包可能具有多个分析字段,简单累加会重复计数。真实丢包评估还涉及未捕获发送、接收端确认与重传范围,因此报告更适合写“候选重发报文占比”并附统计定义。

tshark -r incident.pcapng -Y 'tcp.stream == 0 && (tcp.analysis.retransmission || tcp.analysis.fast_retransmission || tcp.analysis.spurious_retransmission)' -T fields -e frame.number | wc -l

连接重置数量需要区分一条连接多个 RST 与多条连接各一个 RST。下面导出流编号并去重,得到文件内发生重置的流数量。该数量仍受采集窗口影响,中途连接可能没有完整起点。统计应同时记录总连接数和业务请求数,但三者不具有一一对应关系,尤其是连接复用与多路复用协议场景。

tshark -r incident.pcapng -Y 'tcp.flags.reset == 1' -T fields -e tcp.stream | sort -n -u | wc -l

按方向计算 TCP 负载总字节,适合查看谁发送了更多数据。下面仅统计客户端发往服务器的可见负载,重传仍然计入,所以它不是独立有效数据量。需要去重时应按序号区间合并,而不是简单对包长度求和。统计中必须说明方向、窗口和是否包含重发,否则同一个连接的吞吐结论很容易产生矛盾。

tshark -r incident.pcapng -Y 'tcp.stream == 0 && ip.src == 192.0.2.10' -T fields -e tcp.len | awk 'NF {n+=$1} END {print n+0}'

RTT 分布可以离线计算,但空字段和单位必须明确。下面将已有 ACK RTT 导出,再按数值排序,便于读取高值候选。它不是自动计算网络 SLA 的工具,因为采样偏好和确认策略会影响分布。真正发布统计应说明样本数量、百分位算法和排除规则,不能只挑最高的一条时间差代表整个事故期间。

tshark -r incident.pcapng -Y 'tcp.stream == 0 && tcp.analysis.ack_rtt' -T fields -e tcp.analysis.ack_rtt | sort -n > ack-rtt-seconds.txt

下面对 RTT 文件使用明确的最近秩方法计算分位,属于教学分析脚本。样本为空时退出,避免把没有数据报告为零延迟。最近秩与其他插值方法结果可能不同,所以与监控平台比较时要统一定义。样本少时高分位尤其不稳定,应同时报告样本量,不能用三个报文就宣称连接的长期百分之九十九延迟已经得到验证。

import math
values=sorted(float(s) for s in open('ack-rtt-seconds.txt') if s.strip())
if not values: raise SystemExit('no RTT samples')
for q in (0.5,0.95,0.99):
print(q,values[max(0,math.ceil(q*len(values))-1)])
print('samples',len(values))

字段存在性应在现场版本查询,避免从其他版本文章照抄后产生空输出。下面读取字段词汇表,只筛 TCP 相关条目。它是使用工具定义的自检,不代表这些字段在每份文件里都有值。若目标字段不存在,应核对版本与替代字段;如果字段存在但没值,才继续检查协议、采集完整性与解析偏好。

tshark -G fields | awk -F '\t' '$1=="F" && $3 ~ /^tcp\.(analysis|window|seq|ack)/ {print $3,$2}'

解析偏好同样需要记录,尤其是相对序号、TCP 状态分析与重组设置。下面导出当前偏好中相关项,用于和同事复核分析条件。工具版本一致而偏好不同,也可能产生不同显示和标记。事故结论应让别人能够复现相同视图,保存命令、过滤条件和版本比只保存截图更有价值,也能说明统计方法实际依据。

tshark -G currentprefs | grep -E 'tcp\.(relative_sequence_numbers|analyze_sequence_numbers|desegment_tcp_streams)'

路径 MTU、拥塞信号和端点资源,补全报文之外的证据

连接能建立、小响应能返回,大请求却长时间停顿,可能涉及路径 MTU。IPv4 需要分片但设置不可分片时,中间设备可能发送相关 ICMP 错误。下面过滤该类候选,报文内部引用的原始头部有助于关联连接。没有捕获到错误不代表问题不存在,错误可能被过滤,或者采集点看不到;要结合报文大小、隧道开销和两端观察验证。

icmp.type == 3 && icmp.code == 4

IPv6 路由器不会像 IPv4 某些场景那样代替源端分片,过大报文会依赖 Packet Too Big 等反馈。下面筛选对应 ICMPv6 类型,检查报告的 MTU 与原连接。禁止所有 ICMPv6 可能破坏正常网络机制,因此不能为了简单过滤而全量阻断。排障应确认反馈可达和端点是否按反馈调整,避免只把问题归因于服务器 MSS。

icmpv6.type == 2

MSS 在握手中表达对端愿意接收的 TCP 最大段负载,不等于整个路径始终允许的 IP 报文大小。下面导出双向 SYN 中的 MSS,注意隧道和后续路径变化可能改变实际约束。MSS 明显异常时要检查中间设备是否改写,但不能因为两端 MSS 不同就认定错误。各端接口与协议头开销不同,合理差异需要按具体拓扑解释。

tshark -r incident.pcapng -Y 'tcp.flags.syn == 1' -T fields -e frame.number -e ip.src -e tcp.options.mss_val

ECN 提供显式拥塞信号,可以减少只通过丢包推断拥塞的局限。下面筛选 TCP 中相关标志,仍需核对握手协商和 IP 层标记。某个标志存在不直接给出拥塞设备位置,也不代表应用已经明显变慢。它适合与队列、吞吐和延迟趋势关联,帮助区分正常拥塞反馈、兼容性问题与重传恢复行为。

tcp.flags.ece == 1 || tcp.flags.cwr == 1

IP 层 ECN 的拥塞经历值提供另一种候选观察。下面使用 IPv4 字段,IPv6 需要查询相应字段,不应直接复用。标记由路径设备参与,分析仍取决于是否完整看到前后报文。若链路使用封装,还需判断标记位于外层还是内层,只有明确观察层次,才能把拥塞信号和具体业务连接对应起来。

ip.dsfield.ecn == 3

连接数和套接字状态可以解释握手压力、资源耗尽与大量关闭残留。下面读取主机概要,不修改内核参数。TIME_WAIT 多不自动等于故障,它可能是正常高连接率的结果;真正需要检查的是新连接是否失败、端口是否耗尽以及服务接受能力。不能看到一个状态数量大就复制网络调优参数,应先建立业务速率和资源边界。

ss -s

主机网络统计有累计计数,因此事故分析要采集前后差值。下面读取 TCP 扩展统计,具体键名由内核暴露。重传、监听溢出与超时计数可以补充报文文件,但不能直接归属于某个连接或某个应用。把采样时间和服务器负载一同记录,再与抓包时间窗口比较,才能避免用数月累计值解释五分钟内的一次故障。

nstat -az

流编号和报文号可以作为工作文件里的索引,但原件身份应由摘要保存。下面计算抓包文件摘要,便于传递与归档时确认没有误换文件。摘要不判断内容是否真实,也不能补回被截断的报文;它只证明文件字节的一致性。分析中生成的截取和过滤文件应各自标注来源,避免同名文件在多人协作时产生无法解释的结论差异。

sha256sum incident.pcapng selected-stream.pcapng

最后用一份证据清单记录分析限制。下面教学记录保留未知字段,不把它们填写为成功。采集质量、卸载影响、双向可见性与时钟误差都可能改变结论强度。这样交接时,下一位工程师能知道还缺什么信息,也能避免把“暂未看到问题”误解成“已经排除所有网络问题”,从而选择真正有价值的下一次采集。

capture_review:
  file: incident.pcapng
  capture_point: replace_with_actual_location
  handshake_present: unknown
  capture_drops: unknown
  both_directions_visible: unknown
  offload_effect_reviewed: false
  clock_error_bound_ms: null
  confirmed_observations: []

三个虚构故障,从报文现象走到下一步验证

第一个故障是客户端反复发送 SYN,却没有收到 SYN-ACK。客户端文件只能证明请求从当前采集点可见,不能证明它到达服务端。服务端采集若完全看不到请求,应沿路由、防火墙、NAT 和负载均衡入口检查;服务端看到了 SYN 却没有响应,则检查监听、主机策略与资源;服务端发出 SYN-ACK 而客户端看不到,则检查返回路径与客户端侧过滤。三个分支对应不同责任范围,不能把它们压成一句“服务器端口不通”。

第二个故障是下载很慢,文件里出现重复 ACK、SACK 缺口和快速重传。先检查采集丢弃统计,确认不是采集点遗漏;再比较接收端文件是否确实缺少相同序号范围。若发送端发出的段在接收端缺失,且后续重发到达并恢复确认,才有较强依据讨论路径上的丢失。仍然需要结合接口计数、队列、拥塞与中间设备日志,才能把问题定位到具体链路。仅凭 Wireshark 红色提示无法确定哪台交换机有问题。

第三个故障是长连接空闲一分钟后,下次请求收到重置。查看连接池复用时刻、代理空闲超时和 NAT 会话保留时间,往往比关注瞬时带宽更有效。若最短边界是某代理三十秒回收,而客户端连接池保留五分钟,复用陈旧连接就可能出现失败。修复可以让客户端提前回收、采用符合服务需求的保活或统一超时策略,但必须理解设备实际机制。不能把所有超时一律扩大到数小时,因为那会增加连接资源占用与故障恢复时间。

还有一种看似网络故障的情况:请求数据很快被确认,服务端却几十秒后才发响应。TCP ACK 证明协议栈接收了字节,不能证明应用完成处理。此时应关联应用队列、线程池、数据库和外部依赖日志。若服务器同时出现零窗口,则可能是接收端读取受阻;若窗口正常而只是迟迟没有响应,则需要更靠近应用的观测。抓包能够界定等待在哪个阶段,却不能凭一条流自动指出业务内部哪段代码慢。

一个合格的抓包结论应该写出采集位置、时间范围、过滤条件、是否包含握手、采集是否丢包以及可见协议层。随后陈述具体证据,例如“客户端在这些时刻重发同一序号范围”“服务端在接收请求后三秒发出重置”“窗口由服务器方向持续为零”。最后列出已验证的根因或下一步需要的证据。把观察与推断分开,才能让报文分析真正服务于排障,而不是增加一份看似精确却无法复核的猜测。

在云栈社区的技术讨论中,我们经常看到类似的问题:工程师拿着 Wireshark 截图却忽略了采集条件本身可能带来的误导。厘清采集质量与协议语义,永远是第一步。

参考资料

  • Wireshark TCP 分析说明
  • TShark 手册
  • dumpcap 手册
  • TCP 显示过滤字段
  • Wireshark TCP 流图



上一篇:玻璃基板卡在哪一环:AI芯片封装材料革命与量产难题
下一篇:Claude Fable 5.5偷跑首测:暗号识破路由,AI能力断层跃升
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-4 02:41 , Processed in 0.151754 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表