TCP Analysis Flags 之 TCP ACKed unseen segment

2024-08-24 17:28

本文主要是介绍TCP Analysis Flags 之 TCP ACKed unseen segment,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

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

TCP 分析展示

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

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

image.png

TCP ACKed unseen segment 定义

实际在 TCP 分析中,关于 TCP ACKed unseen segment 的定义非常简单,当为反方向设置了期望的下一个确认号并且它小于当前确认号时设置。

Set when the expected next acknowledgment number is set for the reverse direction and it’s less than the current acknowledgment number.

具体的代码如下,涉及到 TCP 分析逻辑还是稍复杂,毕竟涉及到不同方向的 Seq 和 Ack Num 计算,其中还涉及零窗口恢复时候的的一个特殊场景。总之,代码通过识别和处理 TCP 数据流中的 “被 ACK 的丢失数据包” 情况,并调整 maxseqtobeacked变量来反映被 ACK 的最大序列号,从而准确跟踪分析 TCP 连接的状态。

    /* ACKED LOST PACKET* If this segment acks beyond the 'max seq to be acked' in the other direction* then that means we have missed packets going in the* other direction.* It might also indicate we are resuming from a Zero Window,* where a Probe is just followed by an ACK opening again the window.* See issue 8404.** We only check this if we have actually seen some seq numbers* in the other direction.*/if( tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked&&  GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked)&&  (flags&(TH_ACK))!=0 ) {if(!tcpd->ta) {tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);}/* resuming from a Zero Window Probe which re-opens the window,* mark it as a Window Update*/if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)&& (seq==tcpd->fwd->tcp_analyze_seq_info->nextseq)&& (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE) ) {tcpd->rev->tcp_analyze_seq_info->nextseq=ack;tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;}/* real ACKED LOST PACKET */else {/* We ensure there is no matching packet waiting in the unacked list,* and take this opportunity to push the tail further than this single packet*/guint32 tail_le = 0, tail_re = 0;for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next) {if(tail_le == tail_re) { /* init edge values */tail_le = ual->seq;tail_re = ual->nextseq;}/* Only look at what happens above the current ACK value,* as what happened before is definetely ACKed here and can be* safely ignored. */if(GE_SEQ(ual->seq,ack)) {/* if the left edge is contiguous, move the tail leftward */if(EQ_SEQ(ual->nextseq,tail_le)) {tail_le = ual->seq;}/* otherwise, we have isolated segments above what is being ACKed here,* and we reinit the tails with the current values */else {tail_le = ual->seq;tail_re = ual->nextseq; // move the end tail}}}/* a tail was found and we can push the maxseqtobeacked further */if(EQ_SEQ(ack,tail_le) && GT_SEQ(tail_re, ack)) {tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=tail_re;}/* otherwise, just take into account the value being ACKed now */else {tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;}tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;}}
  1. next expected sequence number,为 nextseq,定义为 highest seen nextseq。
  2. lastack,定义为 Last seen ack for the reverse flow。
  3. maxseqtobeacked,定义为 highest seen continuous seq number (without hole in the stream) from the fwd party, this is the maximum seq number that can be acked by the rev party in normal case.If the rev party sends an ACK beyond this seq number it indicates TCP_A_ACK_LOST_PACKET condition。

Packetdrill 示例

根据上述 TCP ACKed unseen segment 定义和代码说明,对于通过 packetdrill 模拟 TCP 连接通讯,仔细琢磨了下,发现不好直接模拟出来,因为 TCP ACKed unseen segment 的现象较为普遍的场景是没有捕获到被 ACK 的数据分段,重点是没有捕获到,而实际端到端 TCP 通讯是正常收到数据分段并确认的。

因此首先第一步简单通过 packetdrill 模拟出一个完整的数据通讯即可,并通过 tcpdump 捕获数据包后,经 Wireshark 展示如下。

# cat tcp_acked_unseen_segment.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 < P. 21:41(20) ack 1 win 15000
+0 < P. 41:61(20) ack 1 win 15000
+0.1 read(4, ..., 60) = 60 
# 

image.png

第二步通过 Wireshark 忽略掉 No.6 数据包即可,也就是说这个 TCP 流中没有捕获到该分段,这样在 No.7 数据包中会判断为 [TCP ACKed unseen segment],因为在反方向最大的可确认的 Seq Num 是 No.4 中的 21 ,小于 No.7 的 ACK Num 41 。

image.png

实例

关于 TCP ACKed unseen segment 的实例,实际日常抓包中经常会看到,是比较常见的一种 TCP 分析信息,多数情况下可认为就是没有捕获到相应的数据分段。当然不同的场景,也会伴生着出现像是 TCP Previous segment not caputredTCP Spurious Retransmission 等信息。

  1. 未捕获到数据分段

最常见的未捕获到一个或多个数据分段时的情景,在这个 TCP 流中没有捕获到反方向从 Seq 1 NextSeq 2401 的分段,这样在 No.120 数据包中会判断为 [TCP ACKed unseen segment],因为在反方向最大的可确认的 Seq Num 是 No.119 中的 1 ,小于 No.120 的 ACK Num 2401 。

image.png

  1. 零窗口的特例

关于从零窗口探测 (Zero Window Probe) 状态恢复的情况,代码判断如果满足以下三个条件:

  1. ACK 值正好是上次 ACK 值加 1。
  2. 当前序列号等于期望的下一个序列号。
  3. 之前的数据段是一个零窗口探测包。

那么就将当前包标记为窗口更新 (Window Update),并更新一些序列号相关的变量。这种情况下不认为是 “被ACK的丢失数据包” 。

以上是关于零窗口探测状态恢复的代码部分解读,结合以下这个实际案例来看,实际是没有出现未捕获数据包的情形的,也因此一开始我对 No.12 标识成 [TCP Window Update] 会感觉疑惑,因为首先需要满足 GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked),也就是 ack num 15622 要大于 maxseqtobeacked,而 maxseqtobeacked 不就应该是 No.11 中的 NextSeq Num 15622 嘛??? 既然相等,也就没有后面代码执行的逻辑,也就不会判断标识成 [TCP Window Update] 了。。。

image.png

但为什么实际会出现 [TCP Window Update] 呢?各方寻求帮助,再加上不断找寻案例,最后在代码中找到了相关说明,确实是零窗口的特例,简单来说就是 [TCP ZeroWindowProbe] 的 NextSeqNum 会被排除,不会更新 maxseqtobeacked,因此对于上面的案例,maxseqtobeacked 的值仍是 No.5 的 NextSeqNum 15621,所以 GT_SEQ 成立。

    /* Store the highest continuous seq number seen so far for 'max seq to be acked',* so we can detect TCP_A_ACK_LOST_PACKET condition.* If this ever happens, this boundary value can "jump" further in order to* avoid duplicating multiple messages for the very same lost packet. See later* how ACKED LOST PACKET are handled.* Zero Window Probes are logically left out at this moment, but if their data* really were to be ack'ed, then it will be done later when analyzing their* Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window).*/if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked=tcpd->fwd->tcp_analyze_seq_info->nextseq;}}
  1. TCP Keep-Alive 的特例

实际并没有未捕获到数据分段,但仍判断为 [TCP ACKed unseen segment] 的特殊场景。
判断为 [TCP ACKed unseen segment] ,是因为在反方向最大的可确认的 Seq Num 是 No.1 中的 1 ,小于 No.2 的 ACK Num 2 ,但如一开始所述,它仅仅是符合了 [TCP ACKed unseen segment] 的代码逻辑,但真实情况并非这样。

image.png

细看下边的数据包,可以发现 No.1 和 No.2 实际是一对 [TCP Keep-Alive][TCP Keep-Alive ACK] ,通过 ip.id 辅助查看,也可以发现 No.1 和 No.3 是连续的数据包,中间并没有多余的数据包,也就是说并不存在数据分段未被捕获到的情形。

image.png

该案例的详细情况,可见《Wireshark TS | 丢包?不要轻易下结论续》。

  1. 消失的 TCP ACKed unseen segment

对于这一种案例,从目前的代码上来说,对于 No.6 确实不会标识成 [TCP ACKed unseen segment] ,因为满足不了 GT_SEQ 的判断。但如下图示,可以很容易看到未捕获到 No.4 和 No.5 之间理应存在的两个分段 Seq 2401 NextSeq 4801,但是在 No.6 ACK 却确认了 6001 以前的所有数据,这不就是一种很明显的 ACKed unseen segment 的情形嘛。

image.png

目前我无法确认是否还有一些特殊的情况考虑在内,在之后的某一天也许可以就这样的案例发起一个 TCP 解析器增强功能的请求。

总结

总的来说,[TCP ACKed unseen segment] 实质上没有任何真实的业务影响,你是否明白了其中的真正原理呢。

这篇关于TCP Analysis Flags 之 TCP ACKed unseen segment的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103128

相关文章

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

【Go】go连接clickhouse使用TCP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么                      🎵 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time""github.com/ClickHouse/clickhouse-go/v2")func main(

2024.9.8 TCP/IP协议学习笔记

1.所谓的层就是数据交换的深度,电脑点对点就是单层,物理层,加上集线器还是物理层,加上交换机就变成链路层了,有地址表,路由器就到了第三层网络层,每个端口都有一个mac地址 2.A 给 C 发数据包,怎么知道是否要通过路由器转发呢?答案:子网 3.将源 IP 与目的 IP 分别同这个子网掩码进行与运算****,相等则是在一个子网,不相等就是在不同子网 4.A 如何知道,哪个设备是路由器?答案:在 A

图解TCP三次握手|深度解析|为什么是三次

写在前面 这篇文章我们来讲解析 TCP三次握手。 TCP 报文段 传输控制块TCB:存储了每一个连接中的一些重要信息。比如TCP连接表,指向发送和接收缓冲的指针,指向重传队列的指针,当前的发送和接收序列等等。 我们再来看一下TCP报文段的组成结构 TCP 三次握手 过程 假设有一台客户端,B有一台服务器。最初两端的TCP进程都是处于CLOSED关闭状态,客户端A打开链接,服务器端

网络原理之TCP协议(万字详解!!!)

目录 前言 TCP协议段格式 TCP协议相关特性 1.确认应答 2.超时重传 3.连接管理(三次握手、四次挥手) 三次握手(建立TCP连接) 四次挥手(断开连接)  4.滑动窗口 5.流量控制 6.拥塞控制 7.延迟应答 8.捎带应答  9.基于字节流 10.异常情况的处理 小结  前言 在前面,我们已经讲解了有关UDP协议的相关知识,但是在传输层,还有

linux下TCP/IP实现简单聊天程序

可以在同一台电脑上运行,在一个终端上运行服务器端,在一个终端上运行客户端。 服务器端的IP地址要和本地的IP相同,并分配端口号,客户端的默认设置为本地,端口号自动分配。 服务器端: #include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.

JAVAEE初阶第七节(中)——物理原理与TCP_IP

系列文章目录 JAVAEE初阶第七节(中)——物理原理与TCP_IP 文章目录 系列文章目录JAVAEE初阶第七节(中)——物理原理与TCP_IP 一.应用层重点协议)1. DNS2 .NAT3. NAT IP转换过程 4 .NAPT5. NAT技术的缺陷6. HTTP/HTTPS7. 自定义协议 二. 传输层重点协议 1 .UDP协议 2.1.1 UDP协议端格式 2.1.2 UD

深入理解TCP通信

这大概是自己博客上面第三次写TCP通信demo了,总是写同样的内容也不太好啊,不过每一次都比前一次进步一点。这次主要使用了VIM编辑工具、gdb调试、wireshirk、netstat查看网络状态。 参考《C++服务器视频教程》、《Unix网络编程》 一、VIM常用命令 vim server.cpp #打开一个文件:w 写入文件:wq 保存并退出:q! 不保存退出显示行号

浏览器工作原理(3)-TCP协议文件如何从服务器到浏览器

浏览器工作原理-TCP协议,文件如何从服务器到浏览器 本周继续学习浏览器工作原理及实践,本次内容来看一下TCP协议确保文件完整的送到至浏览器 First Page 是指页面加载到首次开始绘制的时长,而影响这个性能指标的一个重要原因是网络加载速度,网络传输协议无论使用http还是websocket,都是基于TCP/IP的,所以有必要了解一下TCP/IP,对于web的性能调优和问题定位都有很

应用层简单实现udp / tcp网络通信

一、常见网络接口总结 1、创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器) int socket(int domain, int type, int protocol); domain:AF_INET:网络通信,AF_LOCAL:本地通信 type:UDP:SOCK_DGRAM,TCP:SOCK_STREAM protocol:协议编号一开始设0 返回值:文件描