TCP Analysis Flags 之 TCP ZeroWindowProbe

前言

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

TCP 分析展示

在 TCP 分析中和 TCP 零窗口相关的实际上有三种信息,分别是:TCP ZeroWindowTCP ZeroWindowProbeTCP ZeroWindowProbeAck 。实际运行环境中,有时是单独出现的,譬如 TCP ZeroWindow ,有时是一起出现的,也就是出现了零窗口,之后就会出现需要为恢复窗口而进行的零窗口探测和零窗口探测确认。

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

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

TCP ZeroWindowProbe 和 ZeroWindowProbeAck 定义

实际在 TCP 分析中,关于 TCP ZeroWindowProbe 和 ZeroWindowProbeAck 相关的定义也相对简单,主要说明如下:

  1. TCP ZeroWindowProbe

当满足以下多个条件时设置,包括:

  • 当 Seq Num 等于之前下一个期望的 Seq Num
  • TCP 段大小为 1
  • 反方向最后一次看到的接收窗口大小为零时设置

影响 Fast RetransmissionOut-Of-OrderRetransmission

Set when the sequence number is equal to the next expected sequence number, the segment size is one, and last-seen window size in the reverse direction was zero.

If the single data byte from a Zero Window Probe is dropped by the receiver (not ACKed), then a subsequent segment should not be flagged as retransmission if all of the following conditions are true for that segment: * The segment size is larger than one. * The next expected sequence number is one less than the current sequence number.

This affects “Fast Retransmission”, “Out-Of-Order”, or “Retransmission”.

具体的代码如下,总的来说这段代码的作用是检测零窗口探测包,并对其做出适当的标记,以便 Wireshark 进行后续的分析和显示。 主要检测以下三个条件,如果都满足,则认为是一个零窗口探测数据包。

  • 检查 TCP 段长度是否为 1 字节;
  • 检查 Seq Num 是否等于之前下一个期望的 Seq Num;
  • 检查反方向之前的接收窗口大小是否为 0。
    /* ZERO WINDOW PROBE
     * it is a zero window probe if
     *  the sequence number is the next expected one
     *  the window in the other direction is 0
     *  the segment is exactly 1 byte
     */
    if( seglen==1
    &&  seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
    &&  tcpd->rev->window==0 ) {
        if(!tcpd->ta) {
            tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
        }
        tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
        goto finished_fwd;
    }
  1. next expected sequence number,为 nextseq,定义为 highest seen nextseq。
  2. 关于零窗口探测数据包的定义和说明,段大小为 1 字节,但在 linux 下实测是 0 字节,之后展开说明。
  1. TCP ZeroWindowProbeAck

当满足以下多个条件时设置,包括:

  • TCP 段大小为 0
  • 接收窗口大小为 0
  • Seq Num 是否等于之前下一个期望的 Seq Num
  • Ack Num 等于之前的 LastAck Num
  • 反方向之前数据包是一个零窗口探针

替代 TCP Dup ACK

Set when the all of the following are true:

The segment size is zero.
The window size is zero.
The sequence number is equal to the next expected sequence number.
The acknowledgment number is equal to the last-seen acknowledgment number.
The last-seen packet in the reverse direction was a zero window probe.

Supersedes “TCP Dup ACK”.

具体的代码如下,总的来说这段代码的作用是用于检测零窗口探测的 ACK 包,并对其进行适当的标记和处理,以便 Wireshark 能够正确分析和显示 TCP 流量控制过程中的重要信息。代码逻辑如下,如果所有条件都满足,则认为该 ACK 数据包是对零窗口探测包的响应,包括:

  • 检查 TCP 段长度是否为 0;
  • 检查接收窗口大小是否为 0;
  • 检查接收窗口大小与同方向之前接收窗口大小是否相同;
  • 检查 Seq Num 是否等于同方向之前下一个期望的 Seq Num;
  • 检查 ACK Num 是否等于同方向之前的 LastACK Num,或者是同方向之前的 LastACK Num+1;
  • 检查反方向之前数据包是否是零窗口探测包;
  • 检查当前数据包是否不是 SYN/FIN/RST 数据包。
    /* ZERO WINDOW PROBE ACK
     * It is a zerowindowprobe ack if it repeats the previous ACK and if
     * the last segment in the reverse direction was a zerowindowprobe
     * It also repeats the previous zero window indication
     */
    if( seglen==0
    &&  window==0
    &&  window==tcpd->fwd->window
    &&  seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
    &&  (ack==tcpd->fwd->tcp_analyze_seq_info->lastack || EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1))
    && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
    &&  (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
        if(!tcpd->ta) {
            tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
        }
        tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;

        /* Some receivers consume that extra byte brought in the PROBE,
         * but it was too early to know that during the WINDOW PROBE analysis.
         * Do it now by moving the rev nextseq & maxseqtobeacked.
         * See issue 10745.
         */
        if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)) {
            tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
            tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
        }
        goto finished_fwd;
    }
  1. next expected sequence number,为 nextseq,定义为 highest seen nextseq。
  2. lastack,定义为 Last seen ack for the reverse flow。
  3. 相对于文档介绍,代码中多了一些判断条件,包括像是与之前接收窗口的比较(是否都为 0),Ack Num 等于之前 Ack Num+1的场景。

Packetdrill 示例

根据上述 TCP ZeroWindowProbeTCP ZeroWindowProbeAck 定义和代码说明,起初我认为 packetdrill 是比较容易模拟出来的,只要满足当网络中没有发送且未确认的数据包,且本端有待发送的数据包时,则启动零窗口探测定时器,在超时后发出零窗口探测包,段大小为 1 字节,但是实际按以下 packetdrill 代码模拟后,测试出来的零窗口探测包,段大小为 0 字节,这样在 Wireshark 中会识别为 TCP Keep-Alive 数据包,而不是 TCP ZeroWindowProbe 数据包。

# cat tcp_zero_window_probe.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 1000 <mss 1460>
+0  > S. 0:0(0) ack 1 <...>
+0.01 < . 1:1(0) ack 1 win 1000
+0 accept(3, ..., ...) = 4

+.1 write(4, ..., 1000) = 1000
+0 > P. 1:1001(1000) ack 1
+0.01 < . 1:1(0) ack 1001 win 0

+.1 write(4, ..., 1000) = 1000

+0 `sleep 100000`
# 

以上产生了一个疑问,对于 TCP 零窗口探测数据包,它的数据段是 1 字节还是 0 字节?还是两者都可以?
至少说绝大多数的资料上,都写的是 1 字节,包括 RFC9293 中关于 Zero-Window Probing 的一段说明,截取如下:

The sending TCP peer must regularly transmit at least one octet of new data (if available), or retransmit to the receiving TCP peer even if the send window is zero, in order to "probe" the window.

而且 Wireshark TCP 分析标志定义和源码中也是如此:

Set when the sequence number is equal to the next expected sequence number, the segment size is one, and last-seen window size in the reverse direction was zero.

但是在 Linux (5.15.0) 通过 packetdrill 测试的结果却是 0 字节,因此会被 Wirehshark 识别为 TCP Keep-Alive 数据包,简单翻了下源码,感觉确实是发送序号为 snd_una - 1、长度为 0 的 ACK 包作为探测包,以下少数资料也提到这一点:

https://blog.csdn.net/sinat_20184565/article/details/105691191

https://blog.csdn.net/zhangskd/article/details/44571323

https://www.cnblogs.com/lshs/p/6038654.html

https://blog.csdn.net/weixin_45537413/article/details/114069445

http://www.tcpipguide.com/free/t_TCPWindowManagementIssues-3.htm

其中 TCPIPGUIDE 中的说明:The probe segment can contain either zero or one byte of data, even when the window is closed.

现阶段我的答案是 Windows 系统是 1 字节,Linux 系统(可能是所有版本又或是某个版本之后)是 0 字节。

至少我觉得可以在某个时间提交一个 Issue,和 Wireshark 开发者探讨下,是否能改进相关的判断逻辑。

实例

关于 TCP ZeroWindowProbeTCP ZeroWindowProbeAck 的实例,依赖于 TCP ZeroWindow 的出现,实际日常抓包中并不是经常会看到,但如果看到了,则代表着本端接收窗口为 0 ,意味着本端因性能或容量等问题而无法接收数据,因此通知发送方暂停发送数据,而发送方满足一定条件,启动零窗口探测定时器,在超时后发出零窗口探测包 TCP ZeroWindowProbe ,接收端根据窗口是否恢复的情况回复 TCP ZeroWindowProbeAck 或者 TCP Window Update

  1. TCP ZeroWindow + TCP ZeroWindowProbe + TCP Window Update

一种零窗口情景,接收端出现 Win 为 0 的情形,发送 TCP ZeroWindow 通知,发送端在经过一段时间后发出 TCP ZeroWindowProbe 数据包,但接收端收到探测后,由于已经打开窗口,因此直接回复 TCP Window Update 数据包。

首先服务器端 No.10 Win 为 0 且未设置 SYN、FIN、RST 的情况下,标识为 [TCP ZeroWindow],之后 286ms 客户端发送了 No.11 [TCP ZeroWindowProbe] 用于确认服务器端接收窗口是否恢复,服务器紧接着回复确认 No.12,表示窗口已恢复 Win 1420,标识为 [TCP Window Update] 数据包。

  1. TCP Window Full + TCP ZeroWindow + TCP ZeroWindowProbe + TCP ZeroWindowProbeAck + TCP Window Update

大满贯场景,覆盖了 5 种 TCP 分析标志。首先客户端发送数据,发现服务器接收窗口满了,则在 No.4 和 No.6 上标识 [TCP Window Full] ,此时服务器端 No.7 因为 Win 为 0 且未设置 SYN、FIN、RST 的情况下,标识为 [TCP ZeroWindow],之后陷入等待,大概 2 秒+后,客户端发送了 No.8 [TCP ZeroWindowProbe] 用于确认服务器端接收窗口是否恢复,服务器紧接着回复确认 No.9,表示仍处于零窗口未恢复,标识为 [TCP ZeroWindowProbeAck] + [TCP ZeroWindow] ,又再过了 300ms 后,服务器端发送 No.10 Win 此时更新为 14600,表示接收窗口已恢复,标识成 [TCP Window Update] ,至此完成一次完整的零窗口出现、探测及恢复过程。

类似的场景同样如下

  1. Keep-Alive 零窗口探测特例

在上述 packetdrill 示例中已经提及,TCP 零窗口探测包 0 字节,在 Wireshark 会识别成 TCP Keep-Alive 数据包的特殊示例。

首先服务器端发送数据,发现客户端接收窗口满了,则在 No.5 上标识 [TCP Window Full] ,此时客户端 No.6 因为 Win 为 0 且未设置 SYN、FIN、RST 的情况下,标识为 [TCP ZeroWindow] ,之后因为当网络中没有发送且未确认的数据包,且服务器端有待发送的数据包时,启动了零窗口探测定时器,在超时后发出零窗口探测包,Seq Num 回退 1 为 1000,且段大小为 0 字节,标识成 [TCP Keep-Alive] 。之后因为未模拟客户端回复 ACK 数据包,所以服务器端在未收到确认的情况下,不断超时重传零窗口探测数据包。

总结

套用以前总结的一句话,不要迷信 Wireshark,虽是神器,但不是万能的,只有学到手的东西,才是真正属于自己的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】空指针和野指针

文章目录 1.空指针2.野指针总结 1.空指针 概念&#xff1a;指针变量指向内存中编号为0的空间。 用途&#xff1a;初始化指针变量。 注意&#xff1a;空指针指向的内存是不可以访问的。 示例&#xff1a; int main(){//指针变量p指向内存地址编号为0的空间int *PNULL&#…

在java后端发送HTTPClient请求

简介 HttpClient遵循http协议的客户端编程工具包支持最新的http协议 部分依赖自动传递依赖了HttpClient的jar包 明明项目中没有引入 HttpClient 的Maven坐标&#xff0c;但是却可以直接使用HttpClient原因是&#xff1a;阿里云的sdk依赖中传递依赖了HttpClient的jar包 发送get请…

Django 配置邮箱服务,实现发送信息到指定邮箱

一、这里以qq邮箱为例&#xff0c;打开qq邮箱的SMTP服务 二、django项目目录设置setting.py 文件 setting.py 添加如下内容&#xff1a; # 发送邮件相关配置 EMAIL_BACKEND django.core.mail.backends.smtp.EmailBackend EMAIL_USE_TLS True EMAIL_HOST smtp.qq.com EMAIL…

1.2.2 计算机网络的分层结构(下)

水平视角 YSCS协议&#xff08;压缩传输协议&#xff09; 发送方先压缩然后接收方再解压。 为什么要分层&#xff1f;为什么要制定协议&#xff1f; 计算机网路功能负责->采用分层结构&#xff0c;将诸多功能合理地划分在不同层次->对等层之间制定协议&#xff0c;以…

正则表达式的使用示例--Everything文件检索批量重命名工具

一、引言 Everything是一款非常实用的文件搜索工具&#xff0c;它可以帮助您快速定位并查找计算机中的文件和文件夹。Everything搜索文件资料之神速&#xff0c;有使用过的朋友们都深有体会&#xff0c;相对于Windows自带的搜索功能&#xff0c;使用Everything&#xff0c;可以…

QT将QBytearray的data()指针赋值给结构体指针变量后数据不正确的问题

1、问题代码 #include <QCoreApplication>#pragma pack(push, 1) typedef struct {int a; // 4字节float b; // 4字节char c; // 1字节int *d; // 8字节 }testStruct; #pragma pack(pop)#include <QByteArray> #include <QDebug>int main() {testStruct …

基于VUE的在线手办交易平台购物网站前后端分离系统设计与实现

目录 1. 需求分析 2. 技术选型 3. 系统架构设计 4. 前端开发 5. 后端开发 6. 数据库设计 7. 测试 8. 部署上线 9. 运维监控 随着二次元文化的兴起&#xff0c;手办作为一种重要的周边产品&#xff0c;受到了广大动漫爱好者的喜爱。手办市场的需求日益增长&#xff0c;…

Android-Handle消息传递和线程通信

本文为作者学习笔记&#xff0c;如有误&#xff0c;请各位大佬指点 目录 一、同步异步 二、Java多线程通信 三、Handler是什么 四、Handler相关的类 五、Handler常用方法 1. 发送消息 2. 接收处理消息 3. 切换线程 六、使用Handler 使用Handler更新UI 使用Handler延…

electron教程(三)窗口设置

在main.js文件中&#xff0c;创建窗口时会设置窗口的大小&#xff0c;其实还有很多其他属性&#xff0c;可以根据实际需求选择设置&#xff0c;但部分属性存在局限性&#xff0c;官网也有明确告知&#xff1a;自定义窗口 | Electron (electronjs.org) 项目文件目录如下&#x…

Windows安装Vim,并在PowerShell中直接使用vim

大家好啊&#xff0c;我是豆小匠。 这期介绍下怎么在windows的PowerShell上使用vim&#xff0c;方便在命令行里修改配置文件等。 先上效果图&#xff1a; 1、下载Vim GitHub传送门&#xff1a;https://github.com/vim/vim-win32-installer/releases 选择win-64的版本下载即可&…

信息技术网络安全政策制定

为什么要制定网络安全政策&#xff1f; 通常&#xff0c;公司并不认为需要制定网络安全政策。现有的政策是为了保护公司的资产&#xff0c;而数据也是一项资产。 网络安全政策的真正必要性很简单&#xff1a;网络安全并不像锁门或不偷公司笔那么简单。在许多情况下&#xff0…

HTML的修饰(CSS) -- 第三课

文章目录 前言一、CSS是什么&#xff1f;二、使用方式1. 基本语法2. 引入方式1.行内式2.内嵌式3. 链入式 3. 选择器1. 标签选择器2.类选择器3. id选择器4. 通配符选择器 4. css属性1. 文本样式属性2. 文本外观属性 5. 元素类型及其转换1. 元素的类型2. 元素的转换 6.css高级特性…

【Java的SPI机制】Java SPI机制:实现灵活的服务扩展

在Java开发中&#xff0c;SPI&#xff08;Service Provider Interface&#xff0c;服务提供者接口&#xff09;机制是一种重要的设计模式&#xff0c;它允许在运行时动态地插入或更换组件实现&#xff0c;从而实现框架或库的扩展点。本文将深入浅出地介绍Java SPI机制&#xff…

08_OpenCV文字图片绘制

import cv2 import numpy as npimg cv2.imread(image0.jpg,1) font cv2.FONT_HERSHEY_SIMPLEXcv2.rectangle(img,(500,400),(200,100),(0,255,0),20) # 1 dst 2 文字内容 3 坐标 4 5 字体大小 6 color 7 粗细 8 line type cv2.putText(img,flower,(200,50),font,1,(0,0,250)…

【AI学习】Mamba学习(二):线性注意力

上一篇《Mamba学习&#xff08;一&#xff09;&#xff1a;总体架构》提到&#xff0c;Transformer 模型的主要缺点是&#xff1a;自注意力机制的计算量会随着上下文长度的增加呈平方级增长。所以&#xff0c;许多次二次时间架构&#xff08;指一个函数或算法的增长速度小于二次…

国外电商系统开发-运维系统批量添加服务器

您可以把您准备的txt文件&#xff0c;安装要求的格式&#xff0c;复制粘贴到里面就可以了。注意格式&#xff01; 如果是“#” 开头的&#xff0c;则表示注释&#xff01;

【Qt】控件概述 (1)—— Widget属性

控件概述 1. QWidget核心属性1.1核心属性概述1.2 enable1.3 geometry——窗口坐标1.4 window frame的影响1.4 windowTitle——窗口标题1.5 windowIcon——窗口图标1.6 windowOpacity——透明度设置1.7 cursor——光标设置1.8 font——字体设置1.9 toolTip——鼠标悬停提示设置1…

《安富莱嵌入式周报》第343期:雷电USB4开源示波器正式发布,卓越的模拟前端低噪便携示波器,自带100W电源的便携智能烙铁,NASA航空航天锂电池设计

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 更新一期视频教程 【授人以渔】CMSIS-RTOS V2封装层专题视频&#xff0c;一期视频将常用配置和用法梳理清楚&#xff0…

鸿蒙harmonyos next flutter通信之MethodChannel获取设备信息

本文将通过MethodChannel获取设备信息&#xff0c;以此来演练MethodChannel用法。 建立channel flutter代码&#xff1a; MethodChannel methodChannel MethodChannel("com.xmg.test"); ohos代码&#xff1a; private channel: MethodChannel | null nullthis.c…

openpnp - 图像传送方向要在高级校正之前设置好

文章目录 openpnp - 图像传送方向要在高级校正之前设置好笔记END openpnp - 图像传送方向要在高级校正之前设置好 笔记 图像传送方向和JOG面板的移动控制和实际设备的顶部摄像头/底部摄像头要一致&#xff0c;这样才能和贴板子时的实际操作方向对应起来。 设备标定完&#xf…