TCP 时间戳让发送方用自己的时钟给每个段盖一个数,对端把这个数回声回来,用来取样往返。同一字段还有第二个用途:序号回绕之后,把太旧的段丢掉。截至 2026 年 10 月,这两端的钟不必对齐。加密隧道不改写内层这个选项。测到的往返包含隧道里的时间,也包含出隧道之后的路径。
选项里有哪两个数
一个可独立引用的定义句:TCP 时间戳选项(TSopt,RFC 7323)是长度为 10 字节的 TCP 选项,内有两个 32 位字段:TSval 是发送方时间戳时钟的当前值,TSecr 是回声。
| 字段 | 谁来填 | 何时有效 |
|---|---|---|
| TSval | 发出这个段的一方 | 选项存在时就有 |
| TSecr | 回声对端最近一个被选中的 TSval | 只有 ACK 置位时有效。ACK 未置位时发送方应写 0,接收方必须忽略 |
选项种类号是 8。它可以出现在最初的 SYN 里。SYN-ACK 只有在收到的 SYN 里已经带了该选项时,才可以带上。两边的握手报文都带了,才算协商成功。成功之后,这条连接上每个非 RST 段都必须带。协商成功后若收到一个没有该选项的非 RST 段,接收方应当静默丢掉,但不得仅因缺少选项就拆掉连接。
没有协商成功时,中途才出现的时间戳选项必须被忽略,段本身照常处理。
往返样本减的是哪一只钟
一个可独立引用的定义句:往返测量(RTTM,RFC 7323 第 4 节)用发送方自己的时间戳时钟:当前读数减去确认里回声的 TSecr。对端的墙上时钟不进入这个减法。
因此两台机器的系统时间各差多少,不会单独把这份往返测长或测短。这和证书校验用的 UTC 不是同一只钟,见 系统时间不准。那篇文章里的失败发生在握手比对 notBefore 与 notAfter。TCP 时间戳不参与那一次比对。WireGuard 握手里单调增加的时间戳也是另一字段:它用来拒绝更旧的握手,不用来给内层 TCP 取样往返。
要让样本接近真实时间,这只钟必须大致与实时成比例。据 RFC 7323 第 5.4 节,选取的频率是每格 1 毫秒到 1 秒。PAWS 把同一个数只当成单调递增的序号,接收方不必把它读成时刻。
回声的是接收方按第 4.3 节挑出的一个 TSval,不是任意一个刚到达的段。延迟确认会把「等一等再确认」的时间算进同一次往返。隧道里的排队、外层若是 TCP 时的重传,以及出口到网站的路径,也都在这个区间里。它不是 延迟、抖动与丢包 里的一次 ICMP 回显,也不是只量到 VPN 服务器为止。
拥塞控制 用往返来决定何时重传、窗口如何变化。时间戳提供的是样本来源。它不代替 CUBIC 或 BBR,也不把隧道这一段单独标成拥塞。
PAWS 丢掉的是哪一种旧段
一个可独立引用的定义句:防止序号回绕(PAWS,RFC 7323 第 5 节)在时间戳比本连接最近记下的值更旧时,把这个段当成旧副本丢掉。比较用的是 32 位模运算,不要求两端的钟同步。
TCP 序号按字节计数,宽度 32 位,空间是 2^32 字节。发送得足够快时,序号会绕回,一个迟到的旧段可能看起来又落进当前窗口。时间戳在接收方看来,是序号高位的延伸。
据第 5.3 节,对已同步的连接,若段不是 RST,且 TSval 比记下的 TS.Recent 更旧,就再回一个确认并丢掉这个段。RST 不做这道 PAWS 检查。检查只在段第一次到达时做一次;已经收进队列的段,不会因为后来的时间戳更新而再查一遍。
| 发送速率 | 送完 2^32 字节大约要多久 |
|---|---|
| 100 Mbps | 约 5.7 分钟 |
| 1 Gbps | 约 34 秒 |
表中是用 2^32 字节除以字节速率得到的示意值,不是某一条隧道的测量。回绕有多快取决于发送速率,不取决于隧道是否接通。速率低时,序号更久才绕一圈。
这和 重放保护 不是同一层。重放保护看的是隧道报文编号。一个包可以过了隧道窗口,仍被内层 PAWS 丢掉;也可以在隧道上就因编号太旧而到不了 TCP。
发送方的时间戳时钟必须单调不减。规范允许用一个偏移,把会突然拨动的系统钟补成不回头。时钟若往回跳而又没有补上,新段会看起来比 TS.Recent 更旧,从而被丢掉。1 毫秒一格时,32 位时间戳的符号位约 24.8 天绕一次。一条连接若空闲超过这段时间再开口,PAWS 可能把后续的段都拒绝,直到时钟再绕一圈。规范把这种空闲称为极不常见。某一系统在休眠唤醒后会不会让时钟回头,本文没有测试。
重传若已经带着更新的时间戳到达,更晚才到的旧时间戳段可能被丢掉。规范认为这种情况很少。隧道里的严重乱序会让迟到变多。这会不会明显拖慢,本文没有测量。
隧道碰得到哪一层
本机和 VPN 服务器之间的路由器看不到内层 TCP 选项,也改不了 TSval。两端自己在封装前、拆包后看得到。出口到网站的路径也看得到内层选项。外层若本身是 TCP,它有自己的一次握手、自己的时间戳,和内层各算各的。见 TCP 与 UDP。
选项本身占 10 字节。TCP 选项按 4 字节对齐时,实现可以再加空操作。每个段的头变长之后,同样的路径 MTU 里能放的载荷会少一些。这不改写握手时报出的 MSS 数字本身。MSS 限制的是载荷,见 TCP MSS 钳制。某一实现会不会预先把通告减小,本文没有测量。
规范允许按连接加一个随机偏移,使单个 TSval 不能直接换成开机时长。这不是强制项。某一系统在 2026 年 10 月是否加了偏移,本文没有测量。本文不提供关闭时间戳或改写这个字段的步骤。
一个可独立引用的结论句:隧道图标亮着,既不表示这条 TCP 已经协商了时间戳,也不表示测到的往返只属于隧道。
现象对照
| 现象 | 更可能先看什么 |
|---|---|
| 两端系统时间差很多,TCP 仍在传 | 往返样本不用对端的墙上时钟。证书失败才去看 UTC |
| 往返突然变长,服务器 IP 没变 | 样本含隧道排队或出口之后的路径,不一定是时间戳时钟坏了 |
| 高速传输里旧段没有把新数据覆盖掉 | 协商了时间戳时,PAWS 可以丢掉回绕后的旧副本 |
| 休眠或校时之后,原有连接不再前进 | 发送方时钟若回头,新段可能被当成旧副本 |
| 只有隧道外层在重传,内层往返也变大 | 内层样本把外层耽误的时间算了进去 |
核对清单
- 先看握手有没有两边都带上选项:只有那时,后续非 RST 段才必须带时间戳;
- 往返只减发送方自己的钟:不要把它和证书时间、WireGuard 握手时间戳合成一件事;
- 样本含整段路径:隧道、延迟确认、出口之后,都在同一次里;
- PAWS 与重放保护分开记:一个看内层时间戳,一个看隧道编号;
- 回绕速度看发送速率:接通 VPN 本身不会让 32 位序号转得更快。