摘要

  • RFC 793 在同步状态下把接收窗口内的 RST 视为有效;RFC 5961 把立即复位收紧到序列号与 RCV.NXT 精确相等。
  • 窗口内但不精确的 RST 会收到 challenge ACK,随后被丢弃。真实对端能够用自身状态确认,盲注入者通常看不到这次询问。

问题并不在于 RST 报文本身复杂,而在于它获得了过大的权限。设想一条长时间运行的 TCP 连接,以及一个看不到双向流量的离路径攻击者。攻击者只要不断猜测序列号,其中一个落入当前接收窗口,RFC 793 的原始规则就可能允许该 RST 清除整个连接状态。接收窗口原本回答的是“这些字节是否可能属于此流”,却被顺带用来回答“这个报文是否有权终止此流”。

2010 年的 RFC 5961 重新排列了决定顺序。窗口外 RST 仍然静默丢弃;序列号恰好等于下一个期望字节 RCV.NXT 的 RST 可以复位连接;真正关键的中间情况——报文在窗口内、但并不精确——不再立即生效。接收端发送 <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>,丢弃可疑报文,并照常处理后续流量。

它被称为“挑战 ACK”,因为它把单方面主张变成了需要对端状态才能回答的问题。若远端确实已经关闭或重启,不再持有旧连接的传输控制块,它收到 ACK 后可以按确认号生成新的 RST。第二个 RST 有机会精确命中存活端所期待的序列值。盲注入者通常观察不到挑战,也就难以把粗略的窗口内猜测变成精确答复。

这项修补的历史意义,是把“可受理”与“有权执行”分开。窗口内序列号足以让协议作出回应,却不足以授权不可逆的状态转移。TCP 在“忽略”和“销毁”之间多了第三个动作:先挑战,再等待与真实连接状态一致的证据。

RFC 5961 对同步状态下突然出现的 SYN 也采用类似思路。接收端不论该 SYN 的序列号如何,都发送 challenge ACK,然后停止处理这份报文。伪造 SYN 通常只会让已建立连接的对端看到一个额外的重复 ACK;真正重启的对端已没有旧状态,能够以不同方式回应,最终确认旧连接应当结束。

边界同样重要。challenge ACK 不提供密码学身份认证,也不能抵御能够观察当前序列号和确认号的在路径攻击者。RFC 5961 还记载了一个罕见重启角落:同一地址和端口被重用,又偶然选中某个特定初始序列号。机制提高的是盲目攻击的成本,而不是把 TCP 改造成加密协议。

规范强度也并非一律相同。RST 和 SYN 缓解措施是推荐实现,针对盲数据注入的更严格 ACK 范围检查则是可选项。现行基础规范 RFC 9293 仍保留一般复位处理框架,并把 RFC 5961 列为鲁棒性增强。后来的修补叠加在旧合同之上,没有抹去协议演进的真实痕迹。

一手来源