TCP Analysis Flags 之 TCP Spurious Retransmission

前言

默认情况下,Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态,并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时,会对每个 TCP 数据包进行一次分析,数据包按照它们在数据包列表中出现的顺序进行处理。可以通过 “Analyze TCP sequence numbers” TCP 解析首选项启用或禁用此功能。

TCP 分析展示

在数据包文件中进行 TCP 分析时,关于 “TCP Spurious Retransmission” 一般是如下显示的,包括:

  1. Packet List 窗口中的 Info 信息列,以 [TCP Spurious Retransmission] 黑底红字进行标注;
  2. Packet Details 窗口中的 TCP 协议树下,在 [SEQ/ACK analysis] -> [TCP Analysis Flags] 中定义该 TCP 数据包的分析说明。

  1. 考虑到 TCP 乱序、重传场景的复杂性,专家信息在重传的判断上,前面都会有一个(suspected),表示疑似,说明并不是百分百正确,属于 Note 注意。
  2. 另在专家信息中,对于 TCP Spurious Retransmission 标志位分析同时会增加两种 Note,包括 Spurious Retransmission 和 Retransmission。

TCP Spurious Retransmission 定义

文档中关于 TCP Spurious Retransmission 的定义看起来简单,但实际考虑到 TCP 乱序、重传场景的复杂性,在 TCP 分析中对于 TCP Spurious Retransmission 是与 TCP Out-Of-OrderTCP Fast RetransmissionTCP Retransmission 等在一起判断标记乱序或重传类型,而在不少场景还会有判断出错的问题,当然 Wireshark 考虑到这种情况,也有手动修正的选项,这正好也侧面证明了上面的说法,关于 TCP 乱序、重传的复杂性。

TCP Spurious Retransmission 的定义如下,当以下所有条件都为真时设置:

  • SYN 或者 FIN 标志位设置
  • 不是 Keep-Alive 数据包
  • TCP 段长度大于零
  • 该 TCP 流的数据已被确认,也就是说,反方向之前的 LastACK Num 已被设置
  • 该数据包的 Next Seq Num 小于或等于反方向之前的 LastACK Num

替代 Fast RetransmissionOut-Of-OrderRetransmission

Checks for a retransmission based on analysis data in the reverse direction. Set when all of the following are true:The SYN or FIN flag is set.
This is not a keepalive packet.
The segment length is greater than zero.
Data for this flow has been acknowledged. That is, the last-seen acknowledgment number has been set.
The next sequence number is less than or equal to the last-seen acknowledgment number.Supersedes “Fast Retransmission”, “Out-Of-Order”, and “Retransmission”.

结合实际源码+场景,文档中定义有错误,第1个条件(SYN 或者 FIN 标志位设置)和第3个条件(TCP 段长度大于零)应该是或的关系,而不是与的关系。

具体的代码如下,总的来说这段代码是 Wireshark 中 TCP 分析模块的一部分,用于检测和标识 TCP 数据包中的各种重传类型。它的主要功能是根据当前数据包的序列号、长度、标志位以及之前收到的 TCP 数据包的信息,判断当前数据包是否属于重传,如果是则进一步确定它属于哪种重传类型。

根据分析 TCP 数据包的各种特征,对重传数据包进行分类,有助于更好地理解 TCP 连接中的重传行为,对于诊断网络问题很有帮助。在排除了 KeepAlive 数据包后,如果所有下述条件均满足,则认为该数据包是一个虚假重传包。

  • 检查 TCP 段大小是否大于 0;
  • 检查反方向之前的 LastACK Num 是否不为 0;
  • 检查数据包的 Next Seq Num(seq+seglen)是否小于或等于反方向之前的 LastACK Num。
    /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER* If the segment contains data (or is a SYN or a FIN) and* if it does not advance the sequence number, it must be one* of these three.* Only test for this if we know what the seq number should be* (tcpd->fwd->nextseq)** Note that a simple KeepAlive is not a retransmission*/if (seglen>0 || flags&(TH_SYN|TH_FIN)) {gboolean seq_not_advanced = tcpd->fwd->tcp_analyze_seq_info->nextseq&& (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq));guint64 t;guint64 ooo_thres;if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ) {goto finished_checking_retransmission_type;}/* This segment is *not* considered a retransmission/out-of-order if*  the segment length is larger than one (it really adds new data)*  the sequence number is one less than the previous nextseq and*      (the previous segment is possibly a zero window probe)** We should still try to flag Spurious Retransmissions though.*/if (seglen > 1 && tcpd->fwd->tcp_analyze_seq_info->nextseq - 1 == seq) {seq_not_advanced = FALSE;}/* Check for spurious retransmission. If the current seq + segment length* is less than or equal to the current lastack, the packet contains* duplicate data and may be considered spurious.*/if ( seglen > 0&& tcpd->rev->tcp_analyze_seq_info->lastack&& LE_SEQ(seq + seglen, tcpd->rev->tcp_analyze_seq_info->lastack) ) {if(!tcpd->ta){tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);}tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;goto finished_checking_retransmission_type;}...}finished_checking_retransmission_type:
  1. next expected sequence number,为 nextseq,定义为 highest seen nextseq。
  2. lastack,定义为 Last seen ack for the reverse flow。

Packetdrill 示例

根据上述 TCP Spurious Retransmission 定义和代码说明,通过 packetdrill 模拟在收到对一个数据分段 ACK 已确认的情况下,仍然再次重传同一个数据分段即可,就会认为是 TCP Spurious Retransmission

# cat tcp_spurious_retrans.pkt 
0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0  bind(3, ..., ...) = 0
+0  listen(3, 1) = 0+0 < S 0:0(0) win 16000 <mss 1460>
+0 > S. 0:0(0) ack 1 <...>
+0.01 < . 1:1(0) ack 1 win 16000+0 accept(3, ..., ...) = 4
+0 < P. 1:21(20) ack 1 win 15000
+0 > . 1:1(0) ack 21 <...>
+0 < P. 21:41(20) ack 1 win 15000
# 

经 Wireshark 展示如下,可以看到满足判断条件后,No.6 标识 [TCP Spurious Retransmission] ,是因为客户端发送的数据分段 No.4 Seq Num 1 + Len 20,已由服务器 No.5 ACK 21 确认收到了该数据分段,但是在之后客户端又再次发送了同样一个数据分段 No.6 Seq Num 1 + Len 20,此时 Wireshark 就会认为 No.6 是虚假重传,而 No.7 是一次重复确认。

实例

关于 TCP Spurious Retransmission 的实例,实际日常抓包中不算少见,是一种比较好理解的 TCP 分析标志。在不同的场景中,也会伴生着出现像是 TCP Dup ACKTCP ACKed unseen segmentTCP Previous segment not captured 等信息。

  1. TCP Spurious Retransmission + TCP Dup ACK

一个 ACK 响应慢的的场景,根据 Length 54 长度,可知该数据包跟踪文件是在客户端捕获,IRTT 为 45.7ms,但在客户端收到服务器端 No.181 的数据分段后,理论应该最多几 ms 内说响应 ACK,但是直到 209ms 之后才回复 No.182 ACK,此时在服务器端已产生了超时重传,也就是 No.183,所以在客户端收到 No.183 同样的一个数据分段后,即标识为 [TCP Spurious Retransmission] , 而此次客户端不到 1ms 就响应了 ACK,也就是 [TCP Dup ACK]

  1. TCP Spurious Retransmission + TCP ACKed unseen segment

一个 ACK 丢失的场景,根据客户端 No.6 数据包 ACK Num 9 可知已经收到了服务器端发送的 Seq Num 9 之前的所有数据分段,但往上到 No.4 却没有看到相关数据分段,当然只是没有捕获到,实际上客户端已收到,因此 No.6 标识成 [TCP ACKed unseen segment] ,但为什么看到了 No.6 ACK 了,服务器端仍然重传了 No.7 。实际上这是抓包点的问题,或者说此数据包跟踪文件不是在服务器端上抓的,譬如在中间端抓取,捕获到了 No.6 ACK,但是这个 ACK 再往服务器去传输时丢失了,因此服务器在没收到 ACK 的情况下,重传了 No.7 Seq Num 1 + Len 8 的数据分段,也因此被标识成 [TCP Spurious Retransmission]

  1. 错误的 TCP Spurious Retransmission

错误的 TCP 虚假重传场景,如下所示,No.5-6 发送端所发送的数据分段,因个别未捕获到,标识为 [TCP Previous segment not caputred] ,但接收端 No.9 的 ACK Num 9881 说明已确认接收了序号 9881 之前的数据段,但在 No.11 发送端又重新发送了 Seq Num 4940 + Len 1368 的数据分段,因此符合条件,标识为 [TCP Spurious Retransmission]

一切看起来挺合理,但为什么说是判断错误呢?凡事深想一层,干活多做一步,再瞅瞅 ip.id ,你会发现有些问题。发送端 No.11 的 ip.id 为 29559,这不是应该是在 No.4 和 No.5 之间的一个数据包嘛,所以呢,No.11 不是重传,它是原本的数据分段,也因此它应该被标识成 [TCP Out-Of-Order]

但是为什么会出现这样的情况,乱序的数据段出现在了 ACK 确认之后,虽然不是完全确认抓包的环境,但基本上可以猜测是交换机镜像或者 TAP 出了问题,更有可能是后者造成的乱序。

总结

考虑到数据包会出现乱序、重传等各类不同的场景,产生 TCP Spurious Retransmission 的情形自然也是五花八门,具体问题具体分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/484403.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react 路由鉴权

权限路由一般两种 1中接口中返回菜单 2 接口中返回权限&#xff0c;前端做匹配 一般都是那种结合&#xff0c;react中没有vue那种钩子函数如何做&#xff1f; 在项目中写一个高阶函数&#xff0c;在高阶函数中判断权限、是否登录等操作app.tsx或者man.tsx中使用 《AuthRouter》…

【spring mvc】全局处理请求体和响应体

目录 说明实现效果逻辑图 实现步骤创建公共处理的请求和响应的类api接口测试前端请求响应结果 扩展Response响应格式实体ResponseCode 响应状态码RSA工具类 RequestBodyAdvice 介绍使用场景 ResponseBodyAdvice 介绍使用场景 说明 由于项目中需要进行加密传输数据提高项目安全…

FlyHttp 的设计思想:前端 API 自动化构建工具

FlyHttp的相关文章&#xff1a; FlyHttp 的诞生&#xff1a;从认识各种网络请求开始 FlyHttp 的设计思想&#xff1a;前端 API 自动化构建工具 FlyHttp 的使用&#xff1a;如何高效使用 FlyHttp&#xff0c;支持 JS、TS 项目 FlyHttp 的最佳实践&#xff1a;加速项目级 API…

在CentOS上无Parallel时并发上传.wav文件的Shell脚本解决方案

在CentOS上无Parallel时并发上传.wav文件的Shell脚本解决方案 背景概述解决方案脚本实现脚本说明使用指南注意事项在CentOS操作系统环境中,若需并发上传特定目录下的.wav文件至HTTP服务器,而系统未安装GNU parallel工具,我们可通过其他方法实现此需求。本文将介绍一种利用Sh…

springboot整合flowable工作流

1、工作流介绍 1.Flowable起源于Activiti工作流引擎&#xff0c;由Activiti的主要开发者在2016年创建。它继承了Activiti的众多优点&#xff0c;并在此基础上进行了优化和改进&#xff0c;以提供更加稳定、高效的工作流管理解决方案。Flowable与Activiti有着共同的祖先&#x…

Linux Shell 脚本题目集(2)

1、使用 case 语句根据用户输入的分数&#xff08;0-100&#xff09;输出相应的成绩等级&#xff08;A, B, C, D&#xff09;。 #! /bin/bashread -p "请输入您的分数&#xff08;0-100&#xff09;&#xff1a;" score# 验证输入是否为数字且在0到100之间 if ! [[ …

交换机四大镜像(端口镜像、流镜像、VLAN镜像、MAC镜像)应用场景、配置实例及区别对比

在网络管理中&#xff0c;端口镜像、流镜像、VLAN镜像和MAC镜像都是用于监控和分析网络流量的重要技术。 端口镜像&#xff08;Port Mirroring&#xff09; 定义&#xff1a;端口镜像是将一个或多个源端口的流量复制到一个目标端口&#xff0c;以便于网络管理员能够监控和分析…

Redis(1)

Redis是一个在内存中存储数据的中间件。 1.在内存中存储数据。 通过数据结构来存储&#xff0c;mysql通过表的方式存储数据&#xff0c;是关系型数据库&#xff0c;redis通过键值对存储&#xff0c;key的类型是string&#xff0c;value的类型是非关系型数据库。 2.可编程的 …

基于Pyside6开发一个通用的在线升级工具

UI main.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>MainWindow</class><widget class"QMainWindow" name"MainWindow"><property name"geometry"&…

Linux 系统/etc目录下配置文件分类

目录 一、网络相关配置文件 主机名与 IP 映射类 /etc/hosts /etc/hostname 网络接口配置类 /etc/sysconfig/network-scripts/ifcfg-ens33 DNS 相关类 /etc/resolv.conf /etc/host.conf 网络服务相关类 /etc/hosts.allow文件 /etc/hosts.deny文件 /etc/netconfig …

自由学习记录(28)

C# 中的流&#xff08;Stream&#xff09; 流&#xff08;Stream&#xff09;是用于读取和写入数据的抽象基类。 流表示从数据源读取或向数据源写入数据的矢量过程。 C# 中的流类是从 System.IO.Stream 基类派生的&#xff0c;提供了多种具体实现&#xff0c;每种实现都针对…

Redis3——线程模型与数据结构

Redis3——线程模型与数据结构 本文讲述了redis的单线程模型和IO多线程工作原理&#xff0c;以及几个主要数据结构的实现。 1. Redis的单线程模型 redis6.0之前&#xff0c;一个redis进程只有一个io线程&#xff0c;通过reactor模式可以连接大量客户端&#xff1b;redis6.0为了…

Elasticsearch Serverless 现已正式发布

作者&#xff1a;来自 Elastic Yaru Lin 基于全新无状态&#xff08;stateless&#xff09;架构的 Elasticsearch Serverless 现已正式发布。它采用完全托管方式&#xff0c;因此你可以快速启动项目而无需操作或升级&#xff0c;并且可以使用最新的向量搜索和生成式 AI 功能。 …

Android CoordinatorLayout:打造高效交互界面的利器

目录 一、CoordinatorLayout 介绍及特点 二、使用方法 2.1 创建 CoordinatorLayout 布局 2.2 添加需要协调的子视图 2.3 自定义 Behavior 三、结语 相关推荐 在Android开发中&#xff0c;面对复杂多变的用户界面需求&#xff0c;CoordinatorLayout以其强大的交互管理能力…

基于Java Springboot旅游攻略APP且微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信…

多模态大语言模型的对比

简介 文章主要对比了包括 VideoLLaMA 2 、CogVLM2-video 、MiniCPM-V等模型 目前主流的多模态视觉问答大模型&#xff0c;大部分采用视觉编码器、大语言模型、图像到文本特征的投影模块 目录 简介1. VideoLLaMA 21.1 网络结构1.2 STC connector具体的架构 2. MiniCPM-V 2.62.…

Android渗透环境配置教程

工具 模拟器 ADB brew install android-platform-tools set import cert # cer 证书转为 pem 证书 openssl x509 -inform DER -in cacert.der -out cacert.pem# 获取证书的 hash 值 hash$(openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -n 1)# 将 pem…

Microi吾码|.NET、VUE快速搭建项目,低代码便捷开发教程

Microi吾码&#xff5c;VUE快速搭建项目&#xff0c;低代码便捷开发教程 一、摘要二、Microi吾码介绍2.1 功能介绍2.2 团队介绍2.3 上线项目案例 三、VUE中使用Microi吾码3.1 前期了解3.2 创建第一个低代码应用3.3 接口API使用说明3.4 引擎界面可视化配置&#xff0c;生成API3.…

常见Linux命令(详解)

文章目录 常见Linux命令文件目录类命令pwd 打印当前目录的绝对路径ls 列出目录内容cd 切换路径mkdir 建立目录rmdir 删除目录touch 创建空文件cp 复制文件或目录rm 移除文件或者目录mv 移动文件与目录或重命名cat 查看文件内容more 文件分屏查看器less 分屏显示文件内容head 显…

AI - 如何构建一个大模型中的Tool

AI - 如何构建一个大模型中的Tool 大家好&#xff01;今天我们聊聊一个有趣的技术问题&#xff1a;什么是工具&#xff08;Tool&#xff09;&#xff0c;如何使用聊天模型调用工具&#xff0c;以及如何将工具的输出传递给聊天模型。我们还是基于LangChain来进行讨论&#xff0…