ARC — 认证接收链
ELI5: 想象一份证物链式保管表。每个处理证物的人都在表格上签名,并记录他们收到时的状况。即使证物在处理过程中略有变化,最终收件人也能沿着链条往回追踪,看到它始于经过验证的状态,且仅由可信方处理。ARC 对电子邮件身份验证结果也做同样的事情,当邮件通过中间方传递时进行记录。
为什么存在这个RFC
电子邮件转发是 SPF 和 DKIM 的致命弱点。当消息通过邮件列表、别名或 .forward 规则转发时:
- SPF 失效,因为转发服务器的 IP 未被原始发件人的 SPF 记录授权。
- DKIM 失效,如果中间代理修改消息(添加列表页脚、重写标题、更改编码)。
当 SPF 和 DKIM 在最终目的地都失效时,DMARC 也会失效,消息可能被拒绝或隔离——即使它是合法发送的并通过受信任的基础设施转发的。
ARC(认证接收链),在 RFC 8617 中定义,通过让每个中间代理记录它观察到的认证结果的快照然后对其签名来解决这个问题。最终接收者可以检查链以确定消息在发起点已被认证,即使直接 SPF 和 DKIM 检查现在失效。
工作原理
三个 ARC 头集
处理消息的每个中间代理添加一组三个头,用实例计数器(i=)编号,该计数器在每一跳处递增:
| 头 | 用途 |
|---|---|
ARC-Authentication-Results (AAR) |
记录此中间代理观察到的认证结果(SPF、DKIM、DMARC)。遵循与标准 Authentication-Results 头相同的格式。 |
ARC-Message-Signature (AMS) |
中间代理看到的消息头和正文的类似 DKIM 的签名。使用与 DKIM 相同的签名语法。 |
ARC-Seal (AS) |
对所有先前 ARC 头集加上当前 AAR 的签名。这封存了链,防止任何人篡改或重新排序先前的条目。 |
保管链示例
# alice@example.com 的原始消息
# SPF: pass, DKIM: pass, DMARC: pass
# 跳转 1: lists.org 的邮件列表接收消息
ARC-Authentication-Results: i=1; lists.org;
dkim=pass header.d=example.com;
spf=pass smtp.mailfrom=example.com;
dmarc=pass header.from=example.com
ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.org; s=arc; ...
ARC-Seal: i=1; a=rsa-sha256; d=lists.org; s=arc; cv=none; ...
# lists.org 添加页脚、修改主题、重新发送
# 原始 DKIM 签名现在无效(正文已更改)
# SPF 现在引用 lists.org IP,而不是 example.com
# 跳转 2: 最终目的地 mx.receiver.com
Direct DKIM check: FAIL (body modified by list)
Direct SPF check: FAIL (IP is lists.org, not example.com)
Direct DMARC check: FAIL (neither aligned)
ARC 链验证:
i=1 ARC-Seal: 有效(由 lists.org 签名)
i=1 AAR: 在 lists.org 处 dkim=pass、spf=pass、dmarc=pass
链结论: cv=pass
接收者信任 lists.org => 覆盖 DMARC 失效
# SPF: pass, DKIM: pass, DMARC: pass
# 跳转 1: lists.org 的邮件列表接收消息
ARC-Authentication-Results: i=1; lists.org;
dkim=pass header.d=example.com;
spf=pass smtp.mailfrom=example.com;
dmarc=pass header.from=example.com
ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.org; s=arc; ...
ARC-Seal: i=1; a=rsa-sha256; d=lists.org; s=arc; cv=none; ...
# lists.org 添加页脚、修改主题、重新发送
# 原始 DKIM 签名现在无效(正文已更改)
# SPF 现在引用 lists.org IP,而不是 example.com
# 跳转 2: 最终目的地 mx.receiver.com
Direct DKIM check: FAIL (body modified by list)
Direct SPF check: FAIL (IP is lists.org, not example.com)
Direct DMARC check: FAIL (neither aligned)
ARC 链验证:
i=1 ARC-Seal: 有效(由 lists.org 签名)
i=1 AAR: 在 lists.org 处 dkim=pass、spf=pass、dmarc=pass
链结论: cv=pass
接收者信任 lists.org => 覆盖 DMARC 失效
关键技术细节
链验证 (cv) 标签
ARC-Seal 头包含 cv=(链验证)标签,具有以下三个值之一:
-
cv=none— 这是链中的第一个 ARC 集 (i=1)。没有先前的链要验证。 -
cv=pass— 链中的所有先前 ARC 集都已验证且其封印完整。 -
cv=fail— 链已断裂。先前的 ARC 集验证失效。一旦链标记为fail,就无法修复。
ARC 和 DMARC 覆盖
ARC 不替代 DMARC。相反,它提供接收者在做出 DMARC 覆盖决定时可以使用的额外信息。接收者的逻辑可能是:
- 直接检查 DMARC。如果通过,正常投递。
- 如果 DMARC 失效,检查 ARC 链。如果链有效(
cv=pass)且接收者信任链中的中间代理,覆盖 DMARC 失效。 - 如果 ARC 链无效或中间代理不受信任,照常应用 DMARC 政策。
信任中间代理的决定是本地政策。例如,Gmail 维护受信任 ARC 签署者的列表(主要邮件列表提供商、大学邮件系统等)。
签名要求
ARC 签名使用与 DKIM 相同的密码学格式(RSA-SHA256 或 Ed25519)。签名域在 DNS 中 _domainkey 下的选择器处发布其 ARC 公钥,与 DKIM 密钥发布相同:
arc._domainkey.lists.org. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEB..."
实例编号
ARC 集从 i=1 开始按顺序编号。每个中间代理添加具有下一个编号的集。最终接收者通过依次检查所有封印来验证链。如果任何封印失效或任何实例缺失,整个链无效。
ARC 不做的事
- ARC 不直接认证原始发件人——它记录并传递来自早期跳转的认证结果。
- ARC 不建立对中间代理的信任——接收者必须独立决定信任哪些 ARC 签署者。
- ARC 不防止消息修改——它记录修改发生前的认证状态。
常见错误
- 假设 ARC 被普遍接受: ARC 仍是试验性的(不是标准跟踪)。虽然 Gmail、Microsoft 和其他主要提供商支持它,但并非所有接收者都支持。你不应仅依靠 ARC 来保证可投递性。
- 断裂链: 如果不支持 ARC 的中间代理位于支持 ARC 的两者之间,链有一个缺口。下一个支持 ARC 的跳转将看到缺失的实例编号并将链标记为失效。
- 未发布 ARC DNS 密钥: 如果你运营邮件列表或转发服务并添加 ARC 头但未在 DNS 中发布相应的公钥,验证者无法验证你的 ARC-Seal,断裂链。
- 混淆 ARC 和 DKIM: 虽然 ARC 重用 DKIM 的签名格式,但它们的用途不同。DKIM 认证签署域对消息负责。ARC 记录记录每一跳处认证状态的保管链。
- 作为域所有者忽略 ARC: 虽然域所有者不生成 ARC 头,但理解 ARC 有助于诊断消息通过邮件列表或转发服务时的可投递性问题。
可投递性影响
- 拯救转发邮件: ARC 的主要价值是防止合法邮件在转发后被拒绝。邮件列表、大学别名和公司转发规则都受益于 ARC。
- Gmail 的 ARC 信任: Gmail 使用 ARC 做出 DMARC 覆盖决定。如果消息失效 DMARC 但从受信任的中间代理具有有效的 ARC 链,Gmail 可能将消息投递到收件箱而不是拒绝它。
- Microsoft 支持: Microsoft 365 也评估 ARC 链并在其 DMARC 覆盖逻辑中使用它们,特别是对于来自受信任邮件列表的消息。
-
启用更严格的 DMARC 政策: 没有 ARC,从
p=none移动到p=reject会冒着阻止合法转发邮件的风险。ARC 减轻了这种风险,使域所有者更安全地采用强 DMARC 政策。 - 未来防护: 随着越来越多的中间代理采用 ARC,电子邮件生态系统变得更具弹性。支持 ARC 使你的基础设施能够从日益受信任的转发链中受益。