Sequence Number 与 Acknowledgement Number

定义 & 在 TCP 包中的位置

Sequence Number 和 Acknowledge Number 通常被简称为 Seq 与 Ack,其中后者与 TCP 中的 ACK flag 可能偶尔混淆

在此特别强调

image-20240710-070539.png
TCP 报文头部的格式,来自小林 coding

对于第一个 SYN 包,Seq 值随机选择(这个值被称为 ISN),Ack 值为 0

对于第一个对端响应的 SYN-ACK 包,Seq 值随机选择(与第一个 SYN 选择的 Seq 无关),Ack 值为第一个 SYN 包的 Seq 值 + 1(在 TFO 的情况下,还需要加上传送的数据的大小)

Seq 与 Ack 的作用

  • Seq 用来解决网络包乱序问题

  • Ack 用来解决丢包的问题

计算 Seq / Ack

一般情况下:

有两种理解方式

  • Ack 的值 = 对端 Seq 的值 + 对端包中携带的数据长度

  • Ack 的值 = 期望从发送方接收到的下一个字节的 Seq

Ack 的目的是帮助发送方了解哪些数据已经被成功接收,与包的数量、控制包都无关,只有带有数据的包才会影响到 Ack 的值

注意存在一个特殊情况:对于 SYN 或 FIN 包,即使它们没有携带数据,也需要将值 + 1(如果是 TFO,则是在增加了它携带数据的大小基础上 + 1)

三次握手时

三次握手时,计算 Seq / Ack 时需要「将 SYN 包视为多 1 字节」

image-20240710-073225.png
三次握手时 Seq / Ack 的变化,来自小林 coding

数据传输时

数据传输时,根据传输的包大小确定 Seq / Ack

四次挥手时

四次挥手时,计算 Seq / Ack 时需要「将 FIN 包视为多 1 字节」

问题

Seq / Ack 溢出怎么办?

策略:回绕

在TCP协议中,Seq 是一个 32 位的无符号整数(取值范围是从0到2^32-1),计算 Seq 时,如果溢出,那么就直接给出溢出后的值(相当于重新经过 0 了,即回绕)

因存在窗口机制,因此 TCP 对端可以正确识别到回绕的 Seq 不会产生错误

为什么要随机选择 ISN?

作用一

TCP 握手采用随机序列号(不完全随机,而是随着时间流逝而线性增长,到了 2^32 尽头再回滚),为的就是让攻击者更难以猜测 sequence number,因为伪造的 sequence number 不在合法范围内,而被接收方丢弃,增加安全性。

作用二

最大可能为了防止历史报文被接收:历史建立连接的包可能重传,如果都是从 0 开始那么后续的包延迟到达可能浪费资源。

ISN 是真随机吗?

不是!

根据 RFC793,ISN = M + F(localhost, localport, remotehost, remoteport)

  • M 是一个伪计时器,这个计时器每隔 4 微秒加 1

  • F 是一个 Hash 算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值,要保证 hash 算法不能被外部轻易推算得出

对于一个相同的四元组,要 4.77h 才会出现 ISN 回绕的情况