deepwzh的技术笔记
  • Golang
  • Python
  • Cpp
杂项
前端开发
  • 计算机网络
  • 操作系统
  • 数据库
云原生
Devops
AIGC
关于作者
  • Golang
  • Python
  • Cpp
杂项
前端开发
  • 计算机网络
  • 操作系统
  • 数据库
云原生
Devops
AIGC
关于作者
  • 计算机网络
  • Oauth2
  • 网络工具
  • 学习资料
  • RFC 标准
  • 计算机网络
  • Arp
  • 序列化技术
  • DNS

    • DNS
    • Zone 文件
  • HTTP

    • HTTP
    • OpenAPI
  • Https

    • Https
    • SSL/TLS
    • TLS 指纹
    • Client Hello
  • TCP

    • TCP
    • TCP 选项
    • TCP syn flood 攻击
    • 相关内核参数
    • RST 的集中情况
    • TCP Keepalive
  • 首页

    • 首页
    • test
  • 代理

    • 代理
    • 反向代理

TCP 选项

时间戳选项

TCP 最早在 RFC1323 [] 中引入了 timestamp 选项, 并在后来的 RFC7323 中进行了更新。引入 timestamp 最初有两个目的:

**1.更精确地估算报文往返时间(round-trip-time, RTT) **

2. 防止陈旧的报文干扰正常的连接.

Timestamp 是作为一个 TCP 选项存在于 TCP 首部。如下图所示,一个 timestamp 选项需要占据 首部中的 10 个字节。

Kind: 8
 Length: 10 bytes
 
          +-------+-------+---------------------+---------------------+
          |Kind=8 |  10   |   TS Value (TSval)  |TS Echo Reply (TSecr)|
          +-------+-------+---------------------+---------------------+
             1       1              4                     4

选项的核心数据是两个 32-bit 的时间戳字段.TSval 表示发送端发出该报文时的本地时间戳, 而 TSecr 则负责回放(Echo) 最近一次收到的对端报文中的 TSval 的值。

TSval 和 TSecr 在数值上并没有绝对的大小关系。TSval 是以本地的时钟为基准的, 而 TSecr 则是以对端的时钟为基准的。

以下是一个组典型的时间戳交互过程

TCP  A                                     TCP B

                             <A,TSval=1,TSecr=120> ----->

                  <---- <ACK(A),TSval=127,TSecr=1>

                             <B,TSval=5,TSecr=127> ----->

                  <---- <ACK(B),TSval=131,TSecr=5>

启用 Timestamp 选项需要经过双方的协商,协商在三次握手时完成,如果协商成功,则在后续的报文中, 除了 RST 之外的所有报文均必须包含 Timestamp 选项。

TCP Timestamp 选项虽然能带来好处, 但并不是所有的 TCP 连接都会使用该选项,比如 Windows 系统就是默认不不启用该选项的,而 Linux 系统则是默认启用了该选项。 据 tcpm 的统计,在全球范围内,使用了 TCP Timestamp 的连接比例大概为 60%~70% 。

不支持 TCP Timestamp 的理由是该选项占用的报文长度太多了,它会占用 TCP 报文首部的 10 个字节,而且是每个报文都会有这种损耗。

虚拟时钟

前面提到过,TSval 的值是以本地时钟为基准的,更准确地说是来自一个虚拟的时间戳时钟,这个时钟的流逝必须 与真实时间成比例,但不需要一定与真实时间相同,同时它既不能走得太慢,也不能走得太快

不能走得太慢是为了能更准确地测量报文的 RTT。假设这个时钟 10s 才 tick 一下,那么对于 往返时间为 1s 的 TCP 连接,一端发送报文之后,很有可能会发现收到对端的 ACK 报文中的 TSecr 和当前时钟 的值是一样的,这说明 RTT 为 0 ! 显然,这是十分荒谬的。

不能走的太快是为了防止时间戳回绕的干扰。TCP 协议规定的最大 MSL 为 255s, 显然一次时钟的循环必须大于这个值, 换算下来,32-bit 的时钟 tick 必须大于 59ns。否则,就无法区分两个时间戳之差是否经历了时间戳的回绕。

RFC 规定虚拟时钟的频率为每 1ms 到 1s 一个 tick。 按照 1ms 计算,32-bit 的时间戳回绕一次需要 24.8 天。

https://switch-router.gitee.io/blog/tcp-timestamp/

Prev
TCP
Next
TCP syn flood 攻击