摘要

  • NNTP 的 STARTTLS 不会重建 TCP 连接,却会把应用协议重置到几乎等同于服务器问候之后的状态。
  • 服务器必须忘掉握手前从客户端取得的新闻组和文章位置;客户端也不得依赖握手前取得的能力清单。
  • TLS 只保护当前一跳,并不自动完成 NNTP 用户认证,更不能证明文章作者、此前中继或整条传播路径。

同一条连接,两段不同可信度的历史

RFC 977 中的早期 NNTP 是一场清楚的命令对话:连接建立后,服务器先问候,客户端发命令,服务器用三位状态码回答。这个模型允许双方在会话中积累状态,却没有后来那道 TLS 分界线。

到了 2006 年,明文传送密码已不再合适。独立的加密端口曾是一种做法,但 RFC 4642 选择把 STARTTLS 放进普通 NNTP 会话。服务器回答 382 后,下一个字节立即属于 TLS 握手。命令不能排在它后面,也不能把它夹进流水线;一旦双方对边界理解不同,后续字节将失去确定解释。

握手成功时,连接继续,NNTP 状态却回到最初问候刚结束的位置,而且服务器不会再发一次问候。这种“物理连续、语义重启”不是繁琐礼仪,而是协议拒绝让明文阶段替加密阶段作决定。

为什么必须放弃已选新闻组

NNTP 会记住当前新闻组和当前文章编号。RFC 3977 还说明,CAPABILITIES 返回的是命令发出当时的能力;会话状态或外部事件变化后,清单也可以变化。

TLS 之前,这些信息可能被主动攻击者改写。假如客户端在明文中选了某个组,服务器随后直接把该选择带进加密阶段,那么 TLS 保护的操作仍由未受保护的输入控制。假如客户端继续相信旧能力清单,它也可能把被删改的安全能力当成服务器的真实承诺。

因此 RFC 4642 要求服务器丢弃握手前从客户端获得、又并非由 TLS 本身确认的知识,其中明确包括当前新闻组和文章编号。客户端则应丢弃、且不得依赖握手前从服务器获得的知识,能力清单就是例子。加密保护不了过去,所以过去的结论不能偷偷继承新的可信度。

规则也有精确边界:如果此前执行过 MODE READER,它造成的模式变化不会被逆转。重置不是把所有历史无差别清空,而是回到协议定义的状态,并隔离未经安全层建立的敏感知识。

新清单不是旧清单的复印件

握手之后,客户端应再次发送 CAPABILITIES,并重新协商其他状态。新的清单可能不同:STARTTLS 已经不能再次出现,MODE-READER 也不再广告;依赖客户端证书的认证机制反而可能在此时出现。

这说明能力清单是一张带时间和状态的观测记录,不是服务器永恒不变的产品目录。对安全能力而言,上一段会话的缓存尤其危险,因为攻击者可以在明文响应中删掉 STARTTLS。

有趣的是,协议同时要求两种相反的记忆策略。会话内部必须忘记旧清单,防止污染加密阶段;跨会话却可以记住某台服务器过去曾支持 TLS,如果今天突然消失就报警。前一种遗忘保护状态边界,后一种记忆帮助发现降级。

证书到场,不等于用户已经登录

即便客户端在 TLS 握手中提交了证书,服务器仍处于 NNTP 的未认证状态。证书可以提供身份材料,却不能自动替应用协议作出授权决定。

RFC 4643 给出的顺序很清楚:TLS 之后先重新取得能力清单,再执行 AUTHINFO SASL。如果服务器支持,EXTERNAL 机制可以使用从客户端证书导出的身份;但认证成功仍有独立的 NNTP 响应。支持 STARTTLS 的服务器并不因此必须支持 AUTHINFO 或 EXTERNAL。

这个分层避免了权限偷渡。TLS 可以保护字节并验证对端证书,NNTP 仍要决定这个身份是否有权读、发或转交内容。传输身份和应用权限相关,却不是同一件事。

一段加密链路不是一条私密传播链

RFC 4642 最克制的部分是它对保护范围的限定。Netnews 文章可能经过多台服务器。一对 NNTP 节点使用 TLS,只能说明这一跳获得机密性和完整性保护,不能说明前后所有链路都私密。

同样,某台服务器成功认证了转发方,也不能证明转发方当初如何取得文章,更不能证明文章作者。链路对端、应用用户、文章来源和完整中继路径是四组不同证据。IANA 的 NNTP 参数注册表 把 STARTTLS 登记为传输层安全能力,确认的是标准化语义,不是某个现实网络的部署事实。

NNTP STARTTLS 的历史价值,在于它没有把“已经加密”当成一句万能结论。它保留连接,重建状态;利用证书,却另做认证;保护一跳,却不冒充端到端。安全从选择性遗忘开始:加密阶段只能信任在加密阶段重新建立的事实。

来源