TCP 握手建立序列号空间,不是同步两台机器的时钟
TCP 三次握手建立字节流的两个方向。每端提供自己的初始序列号,并确认另一端的序列号。这是两个独立序列空间,不是共享墙上时钟;应用建立连接不需要两台机器时钟同步。之后的序列号用于标识字节,支持连接内部的排序、重复处理、确认和重传。把序列号与时间混为一谈,会误解握手真正建立的协议状态。 图示普通握手及受控丢包场景;32 位序号按模回绕。connect 成功不等于应用已能提供有效服务。 坏掉的样子 客户端发送带初始序列号的 SYN,服务器回复 SYN-ACK,给出自己的初始序列号并确认客户端 SYN,客户端再确认服务器响应。即使没有应用数据,SYN 也占用序列空间中的一个位置,所以对应确认号增加一。将这些数值当成时间戳,会错误解释报文,还可能把排障引向无关的时钟同步问题,忽略真正缺失的确认或路由。 两端不会在完全相同的时刻改变状态。客户端收到 SYN-ACK 后,connect 可能成功返回,但最后一个确认在到达服务器前丢失。服务器仍可能停留在 SYN-RECEIVED,Linux 工具显示为 SYN-RECV。后续携带适当确认的数据也能完成交换,因此单独第三个报文缺失,并不必然导致永久失败,不能把抓包中的固定三包模式当成唯一合法过程。 TCP 建立成功也不代表应用健康或对端身份可信。服务可能接受连接却无法生成有效响应,代理可能完成客户端这一侧连接,却无法建立另一个独立上游连接。初始序列号选择有助于区分连接实例、抵御预测攻击,但不是身份认证协议,也不会加密字节流。传输状态、应用结果和安全身份需要各自对应的验证,不能由一项成功代替全部。 快速验证 将脚本保存为 check-tcp-handshake.py,准备 Docker 后运行 python3 check-tcp-handshake.py。一次性容器使用 Python 3.11.16、iproute2 6.1.0、nftables 1.0.6 和 tcpdump 4.99.3,在 Linux 6.12.76 上验证。NET_ADMIN 与 SYS_ADMIN 支持嵌套网络命名空间。客户端和目标由新建 veth 相连,不移动宿主接口或发布端口: ...