摘要

  • STARTTLS 保护的是一段 SMTP 连接,而邮件会在多台中继之间排队、落盘、重试。RFC 8689 让安全要求附着于单封邮件:每个支持该扩展的下一跳都要经过身份验证,并继续传递这项要求。
  • 当所有 MX 都无法满足条件时,中继必须停止传输并生成受保护的未投递通知。REQUIRETLS 不是端到端加密;它把“不可明文降级”变成了跨越多段连接的失败规则。

先看队列,不看密码算法。

一台中继里有两封发往同一域名的邮件。它们查到同一组 MX,也遇到同一张过期证书。第一封遵循普通策略:尽量建立 TLS,若策略允许,也可能为了送达而继续。第二封在进入系统时得到一个内部标记。对它来说,不能验证下一跳就意味着不能发送。

两封邮件走的不是不同网络。不同的是谁有权决定“送到”是否仍然算成功。

SMTP 是存储转发系统。一段连接结束后,邮件可能还留在磁盘队列里;下一次连接或许由另一进程、另一机构发起。若安全决定只存在于 TLS 会话,它会随套接字关闭而消失。要约束整条转发链,协议必须把会话中的信号变成邮件自身的处理义务。

2019 年的 RFC 8689 用 REQUIRETLS 完成了这次转换。它最重要的创新不是“再加一层加密”,而是允许一封邮件声明:达不到条件时,正确行为不是少一点保护地继续,而是留下失败证据并停止。

STARTTLS 的边界停在当前连接

1999 年的 RFC 2487 为 SMTP 加入 STARTTLS。当时的困难十分现实:公网邮件依赖互通,如果任何不支持 TLS 的服务器都令投递永久失败,升级会切断大量路径。因此早期规则把送达放在首位,保留了安全协商失败后继续的空间。

2002 年的 RFC 3207 更新了机制。服务器在 EHLO 中公布 STARTTLS,客户端发出命令,收到 220 后进行握手。握手完成,双方必须忘掉明文阶段获得的信息;客户端要在加密通道中重新 EHLO。第二次问候阻止攻击者篡改的旧能力继续支配受保护阶段。

可是,重置回答的是“眼前这两个 SMTP 对端现在能做什么”。它没有回答“服务器把邮件收进队列以后,下一段连接也必须怎样做”。中继可以正确完成第一次 TLS,又在后续交接中回到机会式策略。

后来,收件域获得了域级约束。RFC 7672 用经过 DNSSEC 验证的 TLSA 记录建立 SMTP DANE;RFC 8461 允许域通过 HTTPS 发布并让发送方缓存 MTA-STS 策略,限定可接受的 MX 和证书验证。它们表达收件域的要求,却不能天然区分同一发送队列里哪一封邮件必须把保密性置于送达之上。

一个参数把会话信号变成队列义务

RFC 8689 没有发明新 SMTP 命令。服务器在 EHLO 中公布 REQUIRETLS,客户端则在已有的信封命令后加上无值参数:

MAIL FROM:<sender@example> REQUIRETLS

这个参数不能在任意连接中随口声称。当前连接必须已经使用 TLS;MX 身份要由 DNSSEC 或 MTA-STS 约束;证书要通过受信链或 DANE 验证;最关键的是,完成 STARTTLS 后的第二次 EHLO 必须再次公布 REQUIRETLS。攻击者能修改的明文广告不构成承诺。

接收服务器一旦接受这个参数,就必须给邮件打上需要 REQUIRETLS 处理的标记。RFC 没有规定数据库字段、队列文件格式或内存结构,因为那是实现选择。它规定的是效果:邮件以后再次被发送时,标记必须转化为新的线缆行为。

若本地别名把一封邮件扩展成多个收件地址,每个实例都必须保持相同标记。这里的安全决定属于邮件处理,而不是某个收件人条目碰巧继承的属性。

下一跳需要四类证据

中继从队列取出带标记的普通邮件后,不能只记录“TLS=yes”。它先按 RFC 5321 查找收件域的邮件服务器。若 MX 查询没有 DNSSEC 认证,就要用 MTA-STS 验证服务器名称。随后建立 TLS,并用公钥信任链或 DANE 验证证书。最后,它在受保护通道里重新 EHLO,确认对方仍公布 REQUIRETLS。

这些证据各自回答不同问题。加密说明链路内容不以明文经过;证书或 DANE 说明对端身份;DNSSEC 或 MTA-STS 说明哪个 MX 名称有资格代表收件域;TLS 后的能力广告说明下一台中继愿意保存并继续执行邮件级要求。

任何一个缺口都不能由另一个替代。连接加密了,不代表连的是正确 MX。证书有效,不代表下一台服务器会保存标记。服务器在明文 EHLO 中说过支持,也不代表攻击者无法在握手前后改变观察。

遍历 MX,然后把“不能送”写成结果

首选 MX 若缺少 REQUIRETLS,中继要退出这次尝试并检查其他 MX。它仍可以把同队列里没有该标记的邮件交给这台服务器。安全判断没有把整个域永久列入黑名单;它只限制当前邮件。

若全部候选都失败,中继不得把邮件传给该域。RFC 8689 建议用增强状态码 5.7.30 表示对端不支持 REQUIRETLS,用 5.7.10 表示无法建立需要的加密会话,然后向原始反向路径生成未投递通知。

这一步改变了 SMTP 对失败的理解。机会式策略里,安全协商失败可能打开降级路径;REQUIRETLS 中,同一个失败撤销了发送权。把字节送到并非唯一成功标准。准确报告约束无法满足,比悄悄换一种传输方式更忠于发送者意图。

代价也真实存在。证书配置错误、策略获取异常、某个 MX 未升级,都可能让本来可以到达的邮件排队或退回。扩展没有假装安全免费,而是把成本与选择显式交还给发送者。

退信也可能泄露原信

未投递通知常会引用原邮件头,暴露发件人、收件人、主题或路由线索。如果正向路径拒绝明文,诊断信息却沿反向路径明文返回,安全决定就会在最后一步漏水。

所以,只要原邮件带 REQUIRETLS,由它产生的退信也必须带 REQUIRETLS,不论原始失败是否与 TLS 有关。RFC 还缩小引用范围:退信按 DSN 的 RET=HDRS 处理,即使有人要求 RET=FULL,也不能把完整邮件放进诊断。

反向路径有自己的困境。SMTP 退信使用空反向路径,避免“退信失败再退信”的无限循环;而返回发送域的路线不一定拥有与正向路线相同的能力。标准警告,受保护的退信可能因此丢失,并为无法再产生退信的空反向路径留下特殊处理。

于是,没收到退信不等于邮件已送达。它可能说明诊断本身找不到合规返回路线。系统若只看最终用户邮箱,会把两种失败混为一种沉默。

名叫 TLS-Required 的头字段只允许写 No

RFC 8689 还定义了一个看似反常的邮件头:TLS-Required: No。它不是要求使用明文,而是请求支持该规范的发送中继不要让收件域的 DANE 或 MTA-STS 策略阻断投递。典型场景是给管理员报告其 TLS 证书已损坏:如果报告本身也被坏证书挡住,故障很难被告知。

中继仍应在可用时尝试 STARTTLS。No 改变的是协商或策略验证失败后的处置,而不是首选传输方式。若接收服务器自身拒绝未加密连接,发送者也不能迫使它接受;收件域仍有最终入口控制权。

若信封参数与该头字段同时出现,受保护通道中协商的 MAIL FROM ... REQUIRETLS 优先,头字段在处理上被忽略。一封邮件也不得出现多个 TLS-Required 字段。内容不能借一个弱化信号推翻信封已经承担的强约束。

转发容易,重新起草困难

普通中继可以从入站信封保存标记,再把它放入出站信封。邮件列表、转发服务、Sieve 规则、自动回复器却可能创建一封新邮件。旧 SMTP 事务已经结束,收件人可能成百上千,正文和头部也可能改变。

RFC 8689 要求这些“重新发起者”在可行范围内继承原决定,但承认边界无法完全消失。列表扩展后,一些地址的路径支持 REQUIRETLS,另一些不支持;坚持原要求会令部分订阅者收不到。运行在用户侧的规则甚至看不到入站信封标记。

这揭示了协议与组织之间的接缝。规范能约束诚实中继怎样转交已有邮件,却不能自动判断一次处理究竟还是转发,还是已经产生了新作者、新责任和新目的。

它保护逐跳传输,不隐藏中继里的内容

REQUIRETLS 不是端到端加密。每台 MTA 都终止上一段 TLS,在本地看到明文,再发起下一段。恶意中继可以谎称支持、收下邮件后删除标记。RFC 8689 明确不把这种节点放进威胁模型,因为它本来就已被托付原文。

扩展可以对抗被动窃听、STARTTLS 广告剥离、替换 MX 和合规系统中的意外降级。它不能认证人类作者,不能证明队列磁盘加密,不能让中继看不到内容,也不能从一个成功交接推断完整路径。

IANA 的 SMTP 参数登记表 记录了 REQUIRETLS 及其 RFC 引用。登记证明令牌已标准化,不证明部署率、流量份额或任何运营商真的遵守。

这段历史留下的不是“加密总比失败好”这句口号,而是一种更精细的控制方法。存储转发网络里,决定必须活得比连接久。REQUIRETLS 让一封邮件携带可执行的边界:若下一跳不能维持条件,停止和说明失败,才是被授权的行为。