RFC 7293《Require-Recipient-Valid-Since 头字段与 RRVS SMTP 扩展》中文导读

诚实披露:本页为 IETF RFC 的人类翻译版本,依 IETF Trust 条款可自由再制与翻译;译本由 AI 基于人类权威文献辅助整理生成,非人类原创,仅供学习参考。

本页按 RFC 7293《The Require-Recipient-Valid-Since Header Field and SMTP Service Extension》 原文章节顺序梳理规范要点,并非逐字全文翻译;任何规范性判断均以英文原文为准。原文由 IETF 发布并适用 BCP 78 与 IETF Trust 法律条款,英文原文见 rfc-editor.org/rfc/rfc7293.txt

摘要

RFC 7293 处理的是一个常被忽视却后果严重的邮件安全问题:邮箱地址被回收再分配。它定义了两套机制——SMTP 的 RRVS 扩展与 Require-Recipient-Valid-Since 邮件头字段——让发件方能够表达“我知道预期收件人在某个时间点在用这个地址,我不希望这封邮件被投递给其他任何人”,收件系统据此判定是否阻止投递。

1. 问题与设计目标(原文第 1 节)

第 1 节给出的场景很具体:邮件地址有时会被重新分配给不同的人。例如企业的人事变动会使原本属于离职员工的地址被分配给新员工,或者邮件服务提供商(MSP)让某账号过期后,允许他人注册此前使用过的 local-part。曾向该地址前任所有者发信的人可能并不知道地址已被重新分配,于是造成邮件发到了正确的地址、却到了错误的收件人手里。原文指出,这一情形在与购物、在线账户等相关的事务性邮件上尤其令人担忧。

原文由此提出需求:需要一种方式来指明收件人的某项属性,以便在地址的前任所有者与当前所有者不同时区分二者,并且这件事还需要以尊重隐私的方式完成。

本规范定义的机制让发件方指明该地址分配“有多老”。原文把发件方的语义直白地表述为——“我知道预期收件人在这个时间点在使用这个地址,我不希望这封邮件被投递给其他任何人”。收件系统随后可将该信息与地址分配给当前用户的时间点作比对;若分配时间晚于邮件中所指明的时间点,则当前地址使用者很有可能不是正确的收件人,收件系统可以阻止投递,并且最好把该问题通知原发件方。

第 1 节界定了适用面:主要应用是事务性邮件(如账户信息、密码变更请求及其他自动生成的邮件),而非用户撰写的内容;但在其他情境下也可能有用,例如个人通讯录可以记录某邮件地址被加入的时间,从而以该时间配合本扩展使用。原文最后特别提醒:由于本扩展的用例与隐私问题密切相关,对第 13 节安全考量与第 14 节隐私考量的关注尤为重要,尤其要注意第 13.3 节所述的局限。

2. 两套机制及其强弱之别(原文第 3 节)

第 3 节说明,发信客户端(通常是自动化代理)需要向其所连接的服务器指明:它预期该邮件的目标地址自某个指定时间点起一直处于连续所有权(见第 9 节)之下。该指定时间应是预期收件人把该地址提供给邮件作者的时间,或是预期收件人向发件方再次确认该地址归属的某个更近的时间。

两套机制的能力差别被原文说得很清楚:

SMTP 扩展(第 3.1 节):扩展名为 RRVS,是 “Require Recipient Valid Since” 的缩写。实现该扩展的服务器通告一个额外的 EHLO 关键字 RRVS,它不带关联参数、不引入新的 SMTP 命令、也不改变 MAIL 命令。实现 RRVS 的 MTA 可以在 RCPT 命令上发送或接受一个新参数(MDA 也可接受该参数),参数名为 RRVS,取值为按 RFC 3339 定义的 date-time 时间戳,并附加一条限制:必须不使用 time-secfrac(秒的小数部分)。时间戳后可选地跟一个分号与一个字母,称为“无支持动作”(no-support action),用于指明当发现下游 MTA 不支持该扩展时应采取的行动;有效动作为 R(拒绝,默认)与 C(继续)。形式定义为:

rrvs-param = "RRVS=" date-time [ ";" ( "C" / "R" ) ]

原文补充:该扩展相应地把 RCPT 命令的最大命令长度增加 33 个字符。

头字段(第 3.2 节):其 ABNF 语法为

rrvs = "Require-Recipient-Valid-Since:" addr-spec ";" date-time
       CRLF

时间戳格式差异(第 3.3 节):头字段版本与 SMTP 扩展版本采用了不同的日期时间表达格式,原因是邮件头字段使用的是专属于头字段的日期时间格式,这样处理与该用法保持一致。原文说明同时使用日期与时间是为了与当前实现通常存储时间戳的方式保持一致,也便于携带时区;并坦承在实践中,比“日”更细的粒度未必有用。

3. 发送侧的使用约束(原文第 4 节)

第 4 节说明:当生成的邮件其内容足够敏感、以致作者或作者的管理域(ADMD)希望借本协议防范误投时,它为邮件上的每个收件人邮箱确定一个“最后确认该邮箱归属”的时间戳,然后在发送该邮件时使用 SMTP 扩展。

在出站 MTA 不支持该扩展的情况下,可以改用头字段来穿透该系统。但原文强调,使用头字段只是达成上述目标的“尽力而为”方式,并列出四项缺陷:

  1. 失去在每个处理节点上对支持情况的肯定性确认,也失去在无法确认端到端支持时把邮件退回发起方的选项;
  2. 本协议的着眼点在于影响投递(即事务)而非内容,因此在内容中使用头字段总体上并不恰当;
  3. 该机制在多收件人场景下无法使用,否则会无意间把一个收件人的信息暴露给其他收件人(见第 7 节);
  4. 存在时间戳参数被无意转发的风险——无论是自动转发还是用户有意转发(因为用户代理未必会显示该头字段的存在)——从而暴露给非预期收件人(见第 14.4 节)。

由此得出该节的规范性结论:除非发起方或中继确切知道接收方 MDA 或某个中间 MTA 会正确处理它,否则必须不(MUST NOT)使用头字段形式;并且无论如何,在多收件人情形下应当不(SHOULD NOT)使用。

4. 接收侧处理(原文第 5 节)

第 5 节区分两条求值路径:其一,发信客户端使用了扩展,SMTP 会话的 RCPT TO 命令上带有 RRVS 参数,此时只从那里取用所关心的参数(若存在头字段则忽略之);其二,发信客户端未使用扩展,RCPT TO 上无 RRVS 参数,但邮件中可能存在相应的头字段。

该节还规定了两类边界情形:当连续所有权测试因暂时性原因失败(如数据库不可用或其他可能是临时性的状况)时,按对该邮件的正常暂时性失败流程处理。当因未记录所需数据(邮箱创建或重新分配的日期时间)而无法完成测试时,执行求值的 MDA 会选取一个“该邮箱可能被创建或重新分配的最晚时间点”来使用——例如所有已记录的邮箱创建/重分配时间戳中最早的那个,或该主机首次安装的时间。若无法选出合理的替代时间戳,MDA 以 SMTP 应答码拒收该邮件,最好附带表明该测试无法完成的增强状态码(见第 15.3 节);邮件发起方随后可自行决定是不带 RRVS 保护重发,还是另寻途径联系邮箱所有者。

使用 SMTP 扩展时(第 5.1 节):对支持该扩展的 MTA,要求是在向下一跳 MTA 或 MDA 中继的过程中持续执行 RRVS。接收方 MTA 或 MDA 在观察到 RCPT TO 上的 RRVS 参数后,检查目标邮箱的当前所有者是否连续持有该邮箱、且回溯得足够久以涵盖给定时间点,除非该检查结果为否则予以投递。具体地,MDA 在继续投递前会执行两步:

  1. 若所指邮箱已知为 RFC 2142《Mailbox Names for Common Services, Roles and Functions》中所列的角色账号,则忽略该参数;
  2. 若该地址并非已知的角色账号,且该地址自扩展中指定的时间戳起并非处于连续所有权之下,则对 RCPT 命令返回 550 错误。

中继(第 5.1.1 节):不做邮箱归属检查的 MTA(例如部署在组织边界做 SMTP 入口的 MTA)应当(SHOULD)把 RRVS 扩展参数中继给下一跳 MTA 或 MDA,以便在那里处理。当需要把邮件中继给未通告支持该扩展的另一 MTA,且未指定无支持动作或其值为 R(拒绝)时,处理该邮件的 MTA 必须拒收该邮件,方式为:若正在为引入该邮件的 SMTP 客户端提供同步服务,则对 DATA 命令返回 550 错误;否则生成投递状态通知(DSN)以告知邮件发起方发生了投递失败,并终止后续中继尝试。原文并规定:中继时,若 SMTP 客户端使用了无支持动作,MTA 必须保留该动作。

使用头字段时(第 5.2 节):当收到带 Require-Recipient-Valid-Since 头字段的邮件而未使用 RRVS SMTP 扩展时,接收系统按以下步骤处理:①从邮件中取出那些其收件人未使用对应 RRVS SMTP 扩展的 Require-Recipient-Valid-Since 字段;②丢弃符合下列任一条件的字段——语法无效的、指向 RFC 2142 所列角色账号的、其 addr-spec 部分与 SMTP 会话 RCPT TO 中所列当前收件人不匹配的、或其 addr-spec 部分并非由本 ADMD 负责本地投递的邮箱;③对剩余的每个字段,判断所指地址自相应时间戳起是否处于连续所有权之下,若否则拒收该邮件;④推荐(RECOMMENDED):若执行本地投递,在投递到邮箱前移除该字段的所有实例;若邮件被转发,则移除那些未在步骤②中被丢弃的该头字段实例。

原文说明第四步并非强制,因为并非所有邮件处理代理都有能力剥离头字段,且有时确有保留该字段的理由,例如调试需要,或存在会因此类改动而失效的数字签名(另见第 10 节)。该节还提示:若要在 SMTP 协议内部拒收邮件(而非另行生成拒收邮件),实现本协议的服务器应当同时实现《Enhanced Mail System Status Codes》所述的 SMTP 扩展,并酌情使用第 15.3 节所述的增强状态码。原文并指出,本方式的实现对非参与方而言应是透明的,因为它们通常会忽略该头字段。

第 5.2 节最后重申:该头字段通常加到寄给多个收件人的邮件上;该字段的预期用途涉及作者保护面向单一收件人的事务性或其他敏感数据,因此为每个收件人分别生成独立邮件才是常规做法。

设计取舍(第 5.2.1 节):字段内容中包含地址,是为了支持带该头字段的邮件被转发的场景。原文给出的用例是:用户在时间 D 订阅了服务 S 并确认了其当时所在位置的邮件地址 A;此后用户打算离开原处,于是在别处 B 创建了新邮箱,并把地址 A 配置为转发到 B;S 构造一封发往 A 的邮件、声称该地址在时间 D 有效;A 的接收 MTA 判定当前生效的转发是由当时拥有该邮箱的同一方所创建,从而认定连续所有权测试已满足;如有可能,A 的 MTA 从邮件中移除该头字段,无论移除与否都将其转发至 B;邮件到达 B 时,或者头字段已被移除,或者该头字段并不指向当前的信封收件人,两种情况下 MTA 都予以投递。原文并说明,SMTP 从未要求 RFC5321.MailFrom 与 RFC5321.RcptTo 参数同邮件头字段之间存在任何对应关系,这正是本文档所定义的头字段要包含时间戳所适用的收件人地址的原因。

时钟同步(第 5.3 节):本规范的时间戳部分支持秒级精度。原文指出,尽管不常见,但生成方或接收方的时钟出错并非不可能,这会导致 RRVS 求值结果错误。为把此类风险降到最低,实现本规范的生成方与接收方必须(MUST)使用诸如 NTP 之类的标准时钟同步协议来同步到共同的时钟。

5. 向不支持 RRVS 的下一跳中继(原文第 6 节)

第 6 节处理这样的情形:邮件是使用本扩展收到的,但不会在本地投递、需要继续中继,而将要中继到的 MTA 可能并不符合本规范。此时持有该邮件的 MTA 需在三个动作中择一:

  1. 拒绝继续中继该邮件,最好生成 DSN 以表明失败(推荐);
  2. 把 SMTP 扩展中提供的数据降级为头字段,如第 6.1 节所述(除非满足该节所列条件否则应当不采用,且仅在前一选项不可用时才考虑);
  3. 静默地继续投递,放弃本协议所提供的保护。

原文明确:除非确切知道以如此降级的保护继续中继不会引入不当风险,否则需要避免采用第一项以外的选项。

头字段与扩展的相互转换(第 6.1 节):若 SMTP 服务器 B 从客户端 A 收到带一个或多个 Require-Recipient-Valid-Since 头字段的邮件(推测是因为 A 不支持该 SMTP 扩展),而 B 需要把邮件中继给另一服务器 C(从而自身成为客户端),且 C 通告支持该 SMTP 扩展,则 B 应当删除这些头字段、改用 SMTP 扩展来传递该信息。原文提醒:这种对头部的修改可能影响投递时对头部的后续验证,例如对被修改头部的哈希会产生不同结果,这对某些运营方而言可能是跳过该删除操作的正当理由。

反向情形是:若 B 已通过 SMTP 扩展从 A 收到邮箱时间戳,现在必须把邮件中继给 C,而 C 未通告该 SMTP 扩展,且 B 未拒收该邮件(因为客户端已明确谢绝拒收,见第 5.1.1 节),那么在 B 事先知道最终的 MDA 或另一中间 MTA 支持本机制、能够按本规范处理该头字段的前提下,B 应当添加与所中继目标邮箱相匹配的 Require-Recipient-Valid-Since 头字段及其相应的 valid-since 时间戳。原文重申,第 4 节中关于极为审慎地使用头字段的告诫同样适用于这一中继机制。

6. 多收件人下的头字段问题(原文第 7 节)

第 7 节列举了头字段形式在多收件人下的固有难题。由于 SMTP 的性质,一封带有多个 Require-Recipient-Valid-Since 头字段的邮件可能对应一次面向多个收件人的投递尝试(尤其当其中两个收件人由同一服务器处理时),而只要其中任何一个未通过测试,投递就会对所有这些收件人失败;此时必须二择其一:在 SMTP 会话的 DATA 阶段结束时拒收该邮件(即对所有收件人的投递拒绝),或者在 DATA 结束时接收该邮件、随后为每个失败的收件人生成 DSN。

该节还指出另一层复杂性:一封邮件寄给收件人 A 与 B(推定带有不同时间戳),二者随后都被重定向到同一地址 C。作者未必知晓邮箱 C 当前或过去的归属,甚至未必知道 A 和/或 B 已被重定向。这可能导致两次投递中的一次或两次在 C 处失败,而这很可能让邮件作者困惑——就其所知,他从未向 C 发过邮件。最后,原文提出一个显而易见的担忧:携带多个用户时间戳的邮件在扇出时,随着处理代理数量增加,对时间戳信息的严格管控将非常难以保证。

7. 特殊用途地址(原文第 8 节)

第 8 节以 RFC 3461 处理 DSN 与邮件列表关系的方式为范本,讨论本扩展的类似问题。该节先给出一条总括规则:对于下述所有情形,若邮件到达时并未使用 RRVS,接收方 MTA 应当不(SHOULD NOT)以任一形式(SMTP 扩展或头字段)引入 RRVS——原文的理由是,这等于在替邮件发起方揣测其意图,可能导致不良结果。

8. 连续所有权的定义(原文第 9 节)

第 9 节给出本规范的核心定义:就本规范而言,若自某个给定日期时间起,任何发往该地址的邮件都不会到达该给定日期时间时的所有者以外的任何人,则该地址被定义为自该日期时间起处于连续所有权之下。也就是说,尽管地址可能曾被暂停或以其他方式停用一段时间,但实际投递的任何邮件都只会投递给同一位所有者。原文推定发件方与预期收件人之间存在某种关系,并推定曾有某种确认流程用以确立收件方对邮箱的所有权;但作出此类判定的方法属于本地事务,不在本文档范围内。

该节明确:判定邮箱的连续所有权属于接收站点的本地事务;对“自某时起是否连续所有”这一问题,可能的答案只有“是”“否”与“未知”三种,而“未知”情形下应采取何种行动属于本地策略问题。原文举出两种典型的“未知”:其一,当某域名的控制权发生转移时,若邮箱历史未随之移交(或此前根本未维护),新的域所有者可能无法判定该地址的所有者自所述日期时间起是否连续持有;其二,在邮件到达待投递时,存放邮箱归属数据的数据库恰好暂时不可用——后一种情形按典型的 SMTP 暂时性失败处理即可。

第 9 节末尾还有一条以隐私为出发点的规则:为避免不必要地暴露账户细节,若所指定的地址自创建以来只有一位连续所有者,则任何确认日期时间都应当(SHOULD)被视为通过测试,即便该日期时间早于账户创建的日期时间。

9. 与数字签名的关系(原文第 10 节)

第 10 节指出:本协议规定除例外情形外,在投递时应移除(所使用的)头字段。若一封带该头字段的邮件以覆盖该头字段的方式被数字签名,那么如此修改邮件将使签名失效。但原文的定性很明确——该头字段严格来说只用于隧道传递目的,传输系统的其余部分应把它视为纯粹的痕迹信息(trace information)。因此该节给出规范性要求:该头字段必须不(MUST NOT)被包含在数字签名所覆盖的内容之中。

10. Authentication-Results 结果(原文第 11 节)

第 11 节为 Authentication-Results 机制登记 rrvs 方法及相应结果名,各结果含义如下:

原文说明,当邮件上存在多个收件人时,可通过 Authentication-Results 机制报告多个结果。第 12.3 节给出的示例形如 Authentication-Results: mx.example.com; rrvs=pass smtp.rcptto=user@example.com,原文对其解读为:邮件到达时寄往邮箱 user@example.com,已用所提供的时间戳施加连续所有权测试且测试满足;时间戳本身不被披露

11. 协议交互示例(原文第 12 节)

第 12.1 节的 SMTP 扩展示例展示了服务器在 EHLO 响应中通告 RRVS、客户端在 RCPT TO 上附带时间戳、服务器以增强状态码拒收的完整流程(其中 “C:” 表示 SMTP 客户端发送的数据,“S:” 表示服务器的响应):

C: EHLO client.example.net
S: 250-server.example.com
S: 250 RRVS
C: MAIL FROM:<sender@example.net>
S: 250 OK
C: RCPT TO:<receiver@example.com> RRVS=2014-04-03T23:01:00Z
S: 550 5.7.17 receiver@example.com is no longer valid

第 12.2 节的头字段示例则在 DATA 阶段携带头字段,并同样以 550 5.7.17 拒收,其头字段形如:

Require-Recipient-Valid-Since: receiver@example.com;
  Sat, 1 Jun 2013 09:23:01 -0700

12. 安全考量(原文第 13 节)

滥用对抗(第 13.1 节):原文首先点明本协议自带的信息泄露面——实现本协议的服务器所作的响应可能披露某个既有邮箱的“年龄”信息。因此推荐(RECOMMENDED)实现针对探测攻击的对抗措施。原文给出的示例是:运营方可以跟踪该字段针对某个特定邮箱的出现情况,并观察被提交测试的时间戳;若发现短时间内针对同一邮箱尝试了各式各样的时间戳,则可忽略该字段并静默丢弃该邮件。

建议的使用限制(第 13.2 节):若已知该字段所指邮箱自创建以来只有过单一的连续所有者,或者在该字段所指定的日期时间之前根本不曾存在过(在任何所有者名下),则应当静默忽略该字段并施加正常的邮件处理,从而不泄露这一信息。原文判断,此类字段很可能是重大差错或攻击的产物。该节并建议:使用本规范的邮件作者可以限制只对同样已知实现本规范的收件人加入该头字段,以减少泄露作者与该邮箱之间关系的可能性。原文还补充了域权转移的情形:若整个域的所有权发生转移,新所有者可能不知道此前所有者过去分配过哪些地址,因此无法确知任何地址是否只有过单一所有者、或是否曾经存在过——此时 “unknown” 结果很可能是恰当的。

虚假的安全感(第 13.3 节):这是原文在第 1 节就特意提醒读者关注的一节。其要点是:实现本协议的发送方很可能认为自己的内容因此受到了保护;然而必须考虑到,接收系统可能并未正确实现本协议,或根本没有实现。此外,发送系统使用 RRVS 不过是向接收系统提出的一项请求,该系统可能出于某些本地策略、法律或运营原因选择不阻止投递,这就使发送系统所以为的那份安全性落空,并可能意味着本协议所涉及的时间戳信息被无意间泄露。原文由此得出结论:这一顾虑进一步支持了如下看法——发件方最好只在发往已知且受信任的接收方时才使用本协议

邮箱的重新分配(第 13.4 节):原文直言本规范是对邮件地址重新分配或回收所涉风险的直接回应,并把这种做法称为“本质上危险的实践”;通常预期邮件地址不会有很高的更替或所有权变更频率。该节给出一条运营建议:推荐在两任邮箱所有者之间留出相当长的一段时间,期间该邮箱不接收任何邮件,从而给邮件生成方一个机会去发现前任所有者已不在该地址。

13. 隐私考量(原文第 14 节)

权衡(第 14.1 节):这是理解本规范设计立场的关键一节。原文指出,某些 MSP 允许账号名在长期未使用后过期,这迫使人们在两类潜在的隐私脆弱性之间作出选择,而其中一类对用户的威胁显著大于另一类。自动生成的邮件常被用于传递认证凭据,而这些凭据可能提供对极敏感信息的访问;在邮箱所有权变更后把此类凭据交给错误的一方,可能在前任所有者不知情、未授权的情况下暴露其数据。相比之下,本文档所提方案可能向第三方暴露的信息仅限于邮箱历史相关的信息。鉴于 MSP 已经选择允许在前任所有者不参与的情况下转移邮箱所有权,原文的结论是:本规范所定义的扩展造成的信息泄露,其总体风险远低于把邮件投递给错误一方的风险。

探测攻击(第 14.2 节):如前所述,在探测攻击中使用本扩展或头字段可能披露该邮箱的历史信息。原文指出,泄露任何类型私密信息可能造成的危害都难以预估,因此对这类披露(无论是无意的还是因攻击者探测而发生的)保持敏感是审慎之举;并再次强调,实施针对该能力被滥用的对抗措施需要认真考虑。

第 14 节其余部分还讨论了信封收件人与 To/Cc 头字段不必一致所带来的影响,以及使用中的风险——包括 MDA 可能因疏忽或差错而未执行“投递时移除该头字段”的建议,而由于用户代理往往不渲染全部头字段,该邮件可能被转发给另一方而使其无意中获得该头字段的内容;原文并提醒,不良行为者可能检测到 RRVS 协议任一形式的使用,并将其解读为高价值内容的信号

14. IANA 登记(原文第 15 节)

第 15.1 节记录了 RRVS SMTP 扩展的登记;第 15.2 节把 Require-Recipient-Valid-Since 加入 “Permanent Message Header Field Names”(永久性邮件头字段名称)注册表,适用协议为 mail,状态为 standard,变更控制方为 IETF,并注明建议对该字段的任何拟议变更与新增请求评审。第 15.3 节在 SMTP 增强状态码注册表的枚举状态码表中登记了三个状态码,其关联的基础状态码均为 5XX:

第 15.4 节在 “Email Authentication Methods” 注册表中登记了方法 rrvs,ptype 为 smtp,property 为 rcptto,取值为信封收件人。

15. 术语英文对照

参考链接

参考:https://www.rfc-editor.org/rfc/rfc7293.txt