TCP Analysis Flags 之 TCP Spurious Retransmission

admin 2024年6月17日11:19:10评论2 views字数 5476阅读18分15秒阅读模式

遇事不详,先学数通。

前言

默认情况下,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 数据包的分析说明。

TCP Analysis Flags 之 TCP Spurious Retransmission

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 流的数据已被确认,也就是说,反方向上一个数据包的 ACK Num 已经确认过该数据分段

  • 该数据包的 Next Seq Num 小于或等于反方向上一个数据包的 ACK 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;

  • 检查反方向上一个数据包的 Ack Num 是否不为  0;

  • 检查数据包的 Next Seq Num(seq+seglen)是否小于或等于反方向上一个数据包的 Ack 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:

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 Analysis Flags 之 TCP Spurious Retransmission

实例

关于 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]

TCP Analysis Flags 之 TCP Spurious Retransmission

  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]

TCP Analysis Flags 之 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]

TCP Analysis Flags 之 TCP Spurious Retransmission


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

TCP Analysis Flags 之 TCP Spurious Retransmission

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

总结

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

TCP Analysis Flags 之 TCP Spurious Retransmission

往期推荐

1. Wireshark 提示和技巧 | 捕获点之 TCP 三次握手
2. Wireshark 提示和技巧 | a == ${a} 显示过滤宏
3. Wireshark TS | 防火墙空闲会话超时问题
4. Wireshark TS | 循序渐进看系统访问偶发失败
5. 网络设备 MTU MSS Jumboframe 全解

后台回复「TT」获取 Wireshark 提示和技巧系列 合集
后台回复「TS」获取 Wireshark Troubleshooting 系列 合集
如需交流,可后台直接留言,我会在第一时间回复,谢谢!
TCP Analysis Flags 之 TCP Spurious Retransmission

原文始发于微信公众号(Echo Reply):TCP Analysis Flags 之 TCP Spurious Retransmission

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月17日11:19:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   TCP Analysis Flags 之 TCP Spurious Retransmissionhttps://cn-sec.com/archives/2855050.html

发表评论

匿名网友 填写信息