当前位置: 首页 > news >正文

TCP Analysis Flags 之 TCP Keep-Alive

前言

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

TCP 分析展示

在 TCP 分析中和 TCP Keep-Alive 相关的实际上有两种信息,分别是:TCP Keep-AliveTCP Keep-Alive ACK 。实际运行环境中,有时 TCP Keep-Alive 单独出现的,因为有可能对端未确认 ,有时是一起出现的,也就是对端对 TCP Keep-Alive 数据包进行了确认,回复了 TCP Keep-Alive ACK 数据包。

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

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

TCP Keep-Alive 定义

实际在 TCP 分析中,关于 TCP Keep-AliveTCP Keep-Alive ACK 相关的定义也相对简单,主要说明如下:

  1. TCP Keep-Alive

当 TCP 数据段大小为 0 或 1 时设置,当前序列号比下一个期望的序列号小 1 字节,并且没有设置 SYN、FIN 或 RST。

替代 Fast RetransmissionOut-Of-OrderSpurious RetransmissionRetransmission

Set when the segment size is zero or one, the current sequence number is one byte less than the next expected sequence number, and none of SYN, FIN, or RST are set.Supersedes “Fast Retransmission”, “Out-Of-Order”, “Spurious Retransmission”, and “Retransmission”.

next expected sequence number,为 nextseq,定义为 highest seen nextseq。

具体的代码如下,总的来说这段代码的作用是检测出 TCP 保活包,并对其进行适当的标记,以便 Wireshark 能够正确识别和显示这种特殊的 TCP 控制数据包,帮助分析长连接的保活状态。这段代码的主要逻辑如下,如果所有下述条件均满足,则认为该数据包是一个保活探测包。

  • 检查 TCP 段大小是否为 0 或 1 字节;
  • 检查 Seq Num 比同方向之前的下一个期望的 Seq Num 少 1;
  • 检查当前数据包是否不是 SYN/FIN/RST 数据包。
    /* KEEP ALIVE* a keepalive contains 0 or 1 bytes of data and starts one byte prior* to what should be the next sequence number.* SYN/FIN/RST segments are never keepalives*/if( (seglen==0||seglen==1)&&  seq==(tcpd->fwd->tcp_analyze_seq_info->nextseq-1)&&  (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_KEEP_ALIVE;}
  1. TCP Keep-Alive ACK

当以下所有条件都为真时设置该标志:

  • TCP 段大小为 0
  • 窗口大小非零且没有改变
  • Seq Num 等于之前下一个期望的 Seq Num
  • ACK Num 等于之前的 LastACK Num
  • 最近看到的一个反向数据包是 Keep-Alive
  • SYN、FIN、RST 均未设置

替代 Dup ACKZeroWindowProbeAck

Set when all of the following are true:The segment size is zero.
The window size is non-zero and hasn’t changed.
The current sequence number is the same as the next expected sequence number.
The current acknowledgment number is the same as the last-seen acknowledgment number.
The most recently seen packet in the reverse direction was a keepalive.
The packet is not a SYN, FIN, or RST.Supersedes “Dup ACK” and “ZeroWindowProbeAck”.

具体的代码如下,总的来说这段代码的作用是检测对 TCP 保活包的 ACK 响应,并对其进行适当的标记,以便 Wireshark 能够正确分析和显示 TCP 长连接的保活状态。这段代码的主要逻辑如下,如果所有下述条件均满足,则认为该数据包是一个保活探测响应包。

  • 检查 TCP 段大小是否为 0;
  • 检查窗口大小是否不为 0;
  • 检查当前窗口大小与同方向之前窗口大小是否相同;
  • 检查 Seq Num 是否等于同方向之前下一个期望的 Seq Num;
  • 检查 ACK Num 是否等于同方向之前的 LastACK Num;
  • 检查反方向上一个数据包是否是 TCP Keep-Alive;
  • 检查当前数据包是否不是 SYN/FIN/RST 数据包。
    /* KEEP ALIVE ACK* It is a keepalive ack if it repeats the previous ACK and if* the last segment in the reverse direction was a keepalive*/if( seglen==0&&  window&&  window==tcpd->fwd->window&&  seq==tcpd->fwd->tcp_analyze_seq_info->nextseq&&  ack==tcpd->fwd->tcp_analyze_seq_info->lastack&& (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)&&  (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_KEEP_ALIVE_ACK;goto finished_fwd;}
  1. next expected sequence number,为 nextseq,定义为 highest seen nextseq。
  2. lastack,定义为 Last seen ack for the reverse flow。

Packetdrill 示例

在上述 TCP Keep-AliveTCP Keep-Alive ACK 定义和代码可知,TCP 分析的逻辑相对比较简单,因此通过 packetdrill 比较容易模拟出相关现象。

# cat tcp_keep_alive.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, ..., 500) = 500
+0 > P. 1:501(500) ack 1
+0.1 < . 1:1(0) ack 501 win 1000+0.1 < . 0:0(0) ack 501 win 1000
#

经 Wireshark 展示如下,可以看到满足判断条件后,No.6 标识 [TCP Keep-Alive] ,No.7 标识 [TCP Keep-Alive ACK] ,此时 No.6 的 TCP Len 长度为 0 字节。

同样,可以验证一下 TCP Keep-Alive 数据包 TCP Len 长度为 1 字节的场景,这在 RFC9293 中也明确说明,0 或 1 字节都可以。

# cat tcp_keep_alive_02.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, ..., 500) = 500
+0 > P. 1:501(500) ack 1
+0.1 < . 1:1(0) ack 501 win 1000+0.1 < . 0:1(1) ack 501 win 1000
#

经 Wireshark 展示如下,可以看到满足判断条件后,No.6 标识 [TCP Keep-Alive] ,No.7 标识 [TCP Keep-Alive ACK] ,此时 No.6 的 TCP Len 长度为 1 字节。

实例

关于 TCP Keep-Alive 的实例,正常来说日常抓包中应该比较少看到,TCP Keep-Alive 数据包必须仅在没有未完成的发送数据,且在一定时间间隔内没有收到连接的数据或确认数据包时发送,默认的时间间隔为 2 小时,相对来说很长。

  1. TCP Keep-Alive Len 0 场景

TCP Keep-Alive 数据包 TCP Len 为 0 的场景相对来说更容易碰到。如下 TCP 流在经过 45 秒间隔后,客户端发出了 No.579 [TCP Keep-Alive] , 此时 TCP Len 为 0,之后服务器端响应 No.580 [TCP Keep-Alive ACK]

  1. TCP Keep-Alive Len 1 场景

TCP Keep-Alive 数据包 TCP Len 为 1 的场景相对来说少见。如下 TCP 流在经过 45 秒间隔后,客户端发出了 No.151 [TCP Keep-Alive] , 此时 TCP Len 为 1,之后服务器端响应 No.152 [TCP Keep-Alive ACK],之后每经过 45 间隔后,就继续保活检测和响应。

此案例有意思的是,No.151 TCP Keep-Alive 数据包 Seq Num 为 1155,TCP Len 为 1 ,相较于 No.124 Next Seq Num 1156 以及 No.125 ACK Num 1156,No.151 实际上回退了 1 字节,即所携带的 1 字节数据段为垃圾数据,而对于 No.152 在收到该数据后,除了响应标记 TCP Keep-Alive ACK 之外,同时会标记 [SLE==1155 SRE==1156],说明这 1 个字节的数据之前已收到过,属于重复数据,这属于该 TCP 流建连时均支持 SACK ,其中 D-SACK 的功能实现。

  1. TCP Keep-Alive 无响应场景

无响应的场景没有什么太多要说的,这也是网上经常讨论的,没有数据传输的时候,对端主机宕机或是什么拔掉网线的场景。一端到了规定的时间之后,即发出 TCP Keep-Alive 数据包,对端如果无响应,则每间隔一段时间继续发送探测,持续规定的一定次数之后,中断该连接。在 Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为默认值:

net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75  
net.ipv4.tcp_keepalive_probes=9
  1. 不是 TCP Keep-Alive 的 TCP Keep-Alive 的场景一

一个特殊的例子,仔细看 No.1-2,再对比下标记成 TCP Keep-AliveTCP Keep-Alive ACK 的 No.134-135,你会发现实际的 Seq Num、ACK Num、TCP Len 以及 SLE SRE 基本都是一模一样的。

No.134-135 是 TCP Keep-AliveTCP Keep-Alive ACK,为什么 No.1-2 在这不是?真实的答案是,No.1-2 也是一对 TCP Keep-AliveTCP Keep-Alive ACK 数据包。原因自然是关于数据包跟踪文件中上下文的关系,对于 No.1-2 数据包,它们是这个 TCP 流中抓取的前两个数据包,从 Wireshark 代码判断条件下,它是无法匹配 TCP Keep-AliveTCP Keep-Alive ACK 的判断条件的,因此 No.1-2 不会标记,但实际确实是。

对比一下案例2,和案例4取自同一个跟踪文件,只不过案例2的TCP流中抓取到了前置数据包 No.123-125,因此后续的 TCP Keep-Alive 均能正常识别,而案例4缺少前置数据包,No.1-2 因此不会标记,空空如也。

  1. 不是 TCP Keep-Alive 的 TCP Keep-Alive 的场景二

另一个特殊的例子,其实原因是一样的,均是在 TCP 流中缺少前置数据包,只不过案例 4 中没有任何标记,而在此案例中会被标识为其它,也影响一定判断。

数据包 No.1-2 的类型实际上也是一对 TCP Keep-AliveTCP Keep-Alive ACK 数据包。因为捕获数据包并未抓到之前的包,Wireshark 无法根据上文判断,所以并未标记成 TCP Keep-Alive 数据包,造成之后的数据包 No.2-4 进行 TCP 分析判断时出现偏差,认为是存在丢包情况。

该案例之前在《丢包?不要轻易下结论续》有详细解释,有兴趣的可以瞅瞅。


总结

看似简单的 TCP Keep-Alive ,其实也有大学问,不是嘛。

相关文章:

TCP Analysis Flags 之 TCP Keep-Alive

前言 默认情况下&#xff0c;Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态&#xff0c;并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时&#xff0c;会对每个 TCP 数据包进行一次分析&#xff0c;数据包按照它们在数据包列表中出现的顺序进行处理。可…...

mfc140u.dll丢失怎么办? mfc140u.dll文件缺失的修复技巧

mfc140u.dll 是 Microsoft Foundation Classes (MFC) 库的一部分&#xff0c;它是 Visual Studio 2015 的组件之一&#xff0c;主要服务于使用 C 编写的 Windows 应用程序。这个动态链接库文件包含了 MFC 14.0 Unicode 版本的实现代码&#xff0c;为应用程序提供运行时支持。当…...

Spring Security使用

文章目录 Spring Security的起点FilterChain重写重写登录验证逻辑增加CSRF Token增加方法权限校验 Spring Security的起点 在AbstractApplicationContext.refresh()方法时&#xff0c;子类ServletWebServerApplicationContext会创建一个ServletContextInitializerBeans这个Bea…...

CSS网页布局综合练习(涵盖大多CSS知识点)

该综合练习就是为这个学校静态网页设置CSS样式&#xff0c;使其变成下面的模样 其基本骨架代码为&#xff1a; <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta name"viewport" content…...

解决 Hardhat Verify 超时

问题背景 今天在学习使用Hardhat进行verify 合约 到 Ethscan的时候&#xff0c;出现了如下报错 fafafafadeMacBook-Air Web3_Solidity_Study % npx hardhat verify --network sepolia XXXXXXXXXXXXXXXXXXXXXXXX "10" Successfully verifie…...

ACIS创建各种基本体,举例说明

ACIS&#xff08;Advanced CAD Interoperability System&#xff09;是一个广泛使用的三维几何建模内核&#xff0c;它支持创建和操作各种基本的三维几何体。虽然ACIS没有专门的函数来直接创建某些特定的基本体&#xff08;如椭球体&#xff09;&#xff0c;但可以通过一系列变…...

[CISCN 2019华北]PWN1-好久不见7

Partial RELRO 表示部分 RELRO 保护已启用。在这种情况下&#xff0c;只有某些部分&#xff08;如 GOT 中的只读部分&#xff09;是只读的。 NX enabled 表示这个二进制文件启用了 NX 保护&#xff0c;数据段是不可执行的。这可以防止某些类型的代码注入攻击。 这里是ida识别…...

代码随想录day16| 513找树左下角的值 、 路径总和 、 从中序与后序遍历序列构造二叉树

代码随想录day16| 找树左下角的值 、 路径总和 、 从中序与后序遍历序列构造二叉树 513找树左下角的值层序遍历法递归法 路径总和112. 路径总和113. 路径总和 II 从中序与后序遍历序列构造二叉树思路 513找树左下角的值 层序遍历法 使用层序遍历&#xff0c;找到最后一层最左边…...

使用 MMDetection 实现 Pascal VOC 数据集的目标检测项目练习(二) ubuntu的下载安装

首先&#xff0c;Linux系统是人工智能和深度学习首选系统。原因如下: 开放性和自由度&#xff1a;Linux 是一个开源操作系统&#xff0c;允许开发者自由修改和分发代码。这在开发和研究阶段非常有用&#xff0c;因为开发者可以轻松地访问和修改底层代码。社区支持&#xff1a;…...

书生大模型实战营(第四期)——入门岛

第 1 关 Linux 前置基础 闯关任务完成SSH连接与端口映射并运行hello_world.py10min可选任务 1将Linux基础命令在开发机上完成一遍10min可选任务 2使用 VSCODE 远程连接开发机并创建一个conda环境10min 完成SSH连接 创建python文件 建环境 运行 第 2 关 Python 前置基础 Leet…...

压强随着时间的变化

import numpy as np import matplotlib.pyplot as plt# 参数设置 L 50 # 长度 (m) D 4 # 直径 (m) d 0.01 # 洞的直径 (m) P0 101300 # 初始压力 (Pa) P_final 0.3 * P0 # 最终压力 (Pa) R 287 # 理想气体常数 (J/(kgK)) T 20 273.15 # 温度 (K) M 0.029 # 空…...

2024年大厂AI大模型面试题精选与答案解析

前言 随着AI市场&#xff0c;人工智能的爆火&#xff0c;在接下来的金九银十招聘高峰期&#xff0c;各大科技巨头和国有企业将会对AGI人才的争夺展开一场大战&#xff0c;为求职市场注入了新的活力。 为了助力求职者在面试中展现最佳状态&#xff0c;深入理解行业巨头的选拔标…...

Linux开发讲课47--- 详解 Linux 中的虚拟文件系统

虚拟文件系统是一种神奇的抽象&#xff0c;它使得 “一切皆文件” 哲学在 Linux 中成为了可能。 什么是文件系统&#xff1f;根据早期的 Linux 贡献者和作家 Robert Love 所说&#xff0c;“文件系统是一个遵循特定结构的数据的分层存储。” 不过&#xff0c;这种描述也同样适用…...

全球银行常用英语

Earn OCBC$ or 90 Miles or VOYAGE Miles today! Get the most out of your OCBC Card with OCBC Privileges. 今天赚取华侨银行美元或 90 英里或航程英里&#xff01;通过华侨银行特权充分利用您的华侨银行卡。 Check out the rewards catalogue. Apply for a OCBC Credit Car…...

新160个crackme -090-tc.12

运行分析 需要破解注册码 PE分析 Delphi程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida搜不到字符串&#xff0c;根据Deiphi程序的结构&#xff0c;直接打开来到start函数&#xff0c;找到CreateForm函数的参数off_445FC4&#xff0c;双击 逐个查找偏移&…...

Swagger文档-Unable to scan documentation context default报错

文章目录 报错情况&#xff1a; Unable to scan documentation context 管理端接口发生情况一&#xff1a;发生情况三&#xff1a; 报错情况&#xff1a; Unable to scan documentation context 管理端接口 报错日志&#xff1a; 2024-11-03 12:40:27.427 ERROR 3340 --- [ …...

SpringKafka生产者、消费者消息拦截

1 前言 在Spring Kafka中&#xff0c;可以通过配置拦截器来实现对生产者和消费者消息的拦截。拦截器可以用来记录日志、修改消息等等。 2 基于Kafka管理的拦截器 Kafka原生提供的拦截器接口是org.apache.kafka.clients.producer.ProducerInterceptor和 org.apache.kafka.cli…...

Qt报错QOCI driver not loaded且QOCI available的解决方法

参考 Linux Qt 6安装Oracle QOCI SQL Driver插件&#xff08;适用WSL&#xff09; 安装 QOCI 插件完成后运行 Qt 项目报错&#xff1a; qt.sql.qsqldatabase: QSqlDatabase: QOCI driver not loaded qt.sql.qsqldatabase: QSqlDatabase: available drivers: QMIMER QPSQL QODBC…...

python mac vscode 脚本文件的运行

切换到脚本文件的目录下 路径的修改 当前文件组织形式&#xff1a; 脚本文件在文件夹下&#xff1a; 赋予权限&#xff1a;chmod x ./scripts/fscd_test.sh 运行&#xff1a;./scripts/fscd_test.sh...

Linux之du命令

华子目录 du命令常用选项示例注意事项 du命令 du&#xff08;Disk Usage&#xff09;命令是用于在类Unix操作系统&#xff08;如Linux和macOS&#xff09;中显示文件和目录所占用的磁盘空间大小的工具。它可以递归地计算目录和文件的磁盘使用情况&#xff0c;并提供详细的报告…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...