摘要
- TCP 三次握手不是数据传输前的礼节。它最初的主要目的,是避免一份迟到的旧 SYN 被当成当前连接请求。
- 每个端点各自选择初始序号。应答方可以把“我已看见你的序号”和“这是我的序号”合并进一个 SYN-ACK,但发起方必须再回一个 ACK,才能证明它收到的是这一次挑战。
- 静默期、TIME-WAIT、带秘密偏移的 ISN 与 SYN Cookie 分别处理旧数据、序号猜测和过早占用服务器资源;它们都不等于身份认证。
来自上一段对话的包
互联网会延迟、复制并乱序传送数据。因而,“包到了”不等于“包仍然有效”。一条 TCP 连接关闭后,两个应用可能很快重用相同的源地址、源端口、目的地址与目的端口;上一条连接的 SYN 或数据仍可能在网络中游荡。
接收端看到熟悉的四元组和 SYN 标志,却无法从包本身读出年代。若它把这一份 SYN 当作足够证据,过期请求就可能制造当前状态。
1980 年 1 月的 RFC 761 把问题放进序号空间:两端各自选择初始发送序号,并在建连阶段学习对方的选择。序号能帮助后续数据排序和去重,但前提是先确定这一轮连接究竟从哪里开始。
三个包承载四个事实
同步其实需要四句话:A 告诉 B“我的序号从 X 开始”;B 确认 X;B 告诉 A“我的序号从 Y 开始”;A 再确认 Y。
TCP 把中间两句合并。第一包是 SYN X,第二包是 SYN Y, ACK X+1,第三包是 ACK Y+1。所以逻辑上有四次陈述,线上只需三次传递。
加一不是装饰。SYN 本身占用一个序号位置,因此对方期待 X+1;纯 ACK 不占序号,否则确认还要被再次确认,形成无穷链。1981 年 9 月的 RFC 793 把这套交换写入标准 TCP 状态机。
没有中央连接登记簿,也没有一座为全球 TCP 分配序号的时钟。两端各做本地选择,再用消息把选择变成双方可验证的共同状态。
第三次才是发起方的证明
如果收到 SYN-ACK 就结束,看上去双方都已知道彼此。但对应答方 B 而言,它只知道自己见过 A 的一份 SYN;它不知道 A 是否现在仍记得这份请求。那可能是上一轮连接留下的复制包。
最后一个 ACK 补上这一缺口。它证明当前掌握 A 端状态的一方看见了 B 的 Y,并返回正确确认。RFC 761 把三次握手称为“记忆与消息之间的取舍”:当接收端不可能保存每一对端点历次使用过的全部序号时,就多发一条消息,让表面上的发起者验证当前交换。
这种证明很窄。它证明当前 TCP 状态收到了序号挑战,不证明操作者是谁,不授权应用交易,也挡不住能旁观和改写路径流量的攻击者。
旧包不只需要编号,也需要时间
握手解决连接发起时的旧 SYN,连接关闭后仍有旧数据风险。TCP 因而把序号与时间一起使用:只要携带某序号的包仍可能存在,该序号就没有完全恢复为“空闲”。
早期规范把最大报文生存期 MSL 假定为两分钟。主机若崩溃并丢失近期序号记忆,重启后应静默一个 MSL;若记忆仍在,则可以从已用范围之外继续。
正常关闭后,TIME-WAIT 保留四元组两个 MSL。它既让迟到包耗尽,也允许最后的关闭确认重传。等待不是多余流程,而是防止旧证据获得新含义的一段状态。
当前基础规范 RFC 9293 保留这一模型,同时指出现代实现通常不必真的执行重启静默期:临时端口与 ISN 随机化降低重用概率,包在网络中的有效寿命缩短,重启本身往往已超过危险窗口;高速链路则依靠时间戳与 PAWS 防止序号快速绕回。原则没变,常用工具变了。
TIME-WAIT 也会忘记职责
时间保护只有在实现保留它时才有效。RFC 1337 描述了“TIME-WAIT 暗杀”:旧包抵达后诱发 ACK,而已删除连接状态的对端返回 RST;如果这一 RST 被接受,TIME-WAIT 会提前结束。
同一个四元组马上重开时,旧数据或旧 ACK 可能落进新窗口。文档给出了错误接收数据、双方序号失同步和新连接失败等情形。这并不否定三次握手,而是说明不同机制各守一段边界:握手排除旧 SYN,活动连接的窗口检查排除不合序号的包,TIME-WAIT 隔开前后两次连接。
把互补保护当成重复优化掉,歧义就会重新进入系统。
新鲜序号不是已认证身份
早期规范已经明说,防旧重复包的策略并不防欺骗。若攻击者能预测服务器下一个初始序号,就可能在看不见回复时伪造对方期待的确认。
RFC 6528 加固了 ISN:把计时器与一个使用本地地址、远端地址、双方端口和秘密值的伪随机函数相加。不同四元组得到没有明显外部关系的序号空间,同时保留随时间前进的性质。
它保护的是有限命题:离路径攻击者更难猜中可接受的序号。路径上的观察者仍能看到交换。若系统要确认“对方是谁”,还要在 TCP 之上或传输层内使用密码认证。
把未分配的状态装进挑战
握手还暴露一种资源不对称。开放服务器收到第一份 SYN 后,可能先为半连接分配控制块;伪造者无需完成握手,只要不断发送 SYN,就能塞满队列。
RFC 4987 记录了 SYN Flood 在 1996 年公开并造成运营影响的历史。SYN Cookie 的办法不是取消第三次确认,而是推迟内存承诺:服务器用客户端四元组、客户端序号、时间、少量协商参数和秘密函数构造 SYN-ACK 的序号;最终 ACK 返回时,才验证并重建足够状态。
这相当于把一份紧凑承诺塞进挑战本身。证据回来之前,服务器不必为每个声明保留完整记忆。位数有限会影响某些 TCP 选项,具体算法也并不唯一,所以它不是无代价的魔法。
这段历史真正讲的并非“三个包如何打开 TCP”,而是互联网怎样把若干不同权力拆开:网络只负责转发声明;端点各选序号;相互确认把本地选择变成共享状态;时间限制旧包的意义;秘密降低盲猜;延迟分配限制无人回应的成本。没有一项需要升级成全球会话权威,也没有一项能证明自己观察范围以外的身份或正当性。
来源与证据边界
- https://www.rfc-editor.org/rfc/rfc761.html
- https://www.rfc-editor.org/rfc/rfc793.html
- https://www.rfc-editor.org/rfc/rfc1337.html
- https://www.rfc-editor.org/rfc/rfc4987.html
- https://www.rfc-editor.org/rfc/rfc6528.html
- https://www.rfc-editor.org/rfc/rfc9293.html
RFC 能证明规范内容、设计理由和部分失败分析,不能给出所有 TCP 实现的统一部署日期。本文所说“本地选择经相互证据成为共享状态”是对机制的架构解读,不是 RFC 使用的原词。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
