Defaults.Exposed

Defaults.Exposed修复Guides

DKIM“Body Hash Did Not Verify”——是什么改动了你的邮件,以及怎么修(2026)

发布于 2026-07-08

数据截至 2026-06-29 · 方法论 v7。 基于 261 百万个已评分域名的汇总普查数据。参见我们如何评分

“Body hash did not verify”意味着邮件离开你时 DKIM 签名是有效的——之后有东西改写了邮件正文。签名没坏;是邮件在传输途中被修改了。根据 Defaults.Exposed 对 261,086,232 个域名的普查(2026-06-29),只有 3.87% 的域名——10,092,481 个——凑齐了 SPF-DKIM-DMARC 完整三件套。

修复是一场追查,然后一个决定。找到那个改动你邮件的节点——追加免责声明的网关、改写链接的安全设备、加页脚的邮件列表。然后按顺序三选一:在那个节点之后签名、停止改动,或让签名容忍它。

“body hash did not verify”到底是什么意思?

DKIM 签名(RFC 6376)携带两个哈希:bh=,签名时邮件正文的哈希;b=,对标头加该正文哈希的签名。验证方用收到的邮件重新计算正文哈希;如果和 bh= 对不上,验证就此打住,留下那串人人都会贴进搜索框的文字——一条类似这样的接收方标头:

Authentication-Results: …; dkim=fail (body hash did not verify)

这是 Microsoft 文档中的原因字符串;Gmail 常把同一诊断显示为 dkim=neutral (body hash did not verify)。无论哪种,这个裁决都把问题范围大大收窄了。你的 DNS 密钥、选择器、签名配置全都没问题。密码学尽了职责:正文在签名与验证之间变了——追加一行、改写一个 URL、重新编码一个字符就足够。(不同的信息——signature did not verifyno key for signature——意味着不同的故障;从“DKIM signature not valid”看起。)它之所以紧迫,是因为失败的签名无法给 DMARC 一个对齐的通过:除非同一封邮件的 SPF 以对齐方式通过,否则邮件就直接 DMARC 失败。

是什么改动了你的邮件?惯犯名单

投递路径上有东西在签名封印之后编辑了正文。实践中就是这四种之一:

谁改的改了什么典型特征
出站网关 / smart host(Exchange 传输规则、Mimecast、Proofpoint、Barracuda……)在邮件服务器已经签名之后追加法律免责声明、营销页脚或“EXTERNAL:”横幅走该路由的邮件全部失败;绕过网关的直发通过
安全设备 / 链接保护把 URL 改写成扫描跳转,加追踪包装只有含链接的邮件失败
邮件列表(Google Groups、Mailman……)加主题标签和列表页脚,有时重排正文只有经列表发出的邮件失败
转发方 / 重新编码 MIME 的中继转换字符集、重新折行——人眼看不见,对哈希是致命的失败集中在某一个收件人或转发地址

先查加粗那一行——邮件服务器签名,边缘设备编辑,每封邮件出门时带着一个只真实存在了三十毫秒的签名。

怎么找到正在改动我邮件的那个节点?

鉴别诊断——拿一条能通的路径和失败的路径做对比:

  1. 向你控制的一个大型接收方邮箱(Gmail 就很合适)发一封直发测试邮件,尽量绕开你的出站链路。
  2. 沿失败路径发第二封——经网关、经列表、发往受影响收件人的域名。
  3. 对比两份完整标头里的 Authentication-Results 行。直发 dkim=pass,失败路径 dkim=fail(或 dkim=neutral)且带 body hash did not verify:改动者就住在这两条路由的差集里。
  4. 看收到的正文:有你没打过的免责声明、横幅或页脚?链接被改写到某个扫描域名?那就是你的节点,名字都有了——Received: 链还会显示哪个中继只出现在失败路径上。

你的 DMARC 汇总报告在更大尺度上讲着同一个故事:某个来源持续报告 DKIM 失败而 SPF 通过,通常就是你自己路由上的传输途中修改,不是攻击者。

怎么修?

  1. 动手之前先在 defaults.exposed 运行免费扫描。 它确认你发布的 DKIM 密钥和 DMARC 策略没有问题,这样你调试的就是那一个真问题——改动本身——而不是在 DNS 里追鬼影。修复 DKIM 页面覆盖了记录侧的检查。
  2. 在改动节点之后签名。 架构上正确的修法:把 DKIM 签名移到接触邮件的最外层设备。用 Exchange 加网关的机构应当在网关签名(Mimecast、Proofpoint 及同类都支持),并停用上游签名。如果 Google Workspace 或 Microsoft 365 是你的最后一跳,就在那里签名,并且不让任何东西在它之后编辑邮件——见在 Google Workspace 配置 DKIMMicrosoft 365
  3. 或者停止改动。 把编辑从传输路径上拿走:免责声明放进客户端签名或模板,而不是传输规则;“EXTERNAL:”横幅只限定到入站邮件(把自家出站邮件标成外部,是错上加错的配置);已认证的出站邮件豁免链接改写。
  4. 使用 relaxed/relaxed 规范化(c=relaxed/relaxed)。 simple 正文规范化在一行被重新折行时就失败;relaxed 容忍空白和行尾变化。对局限要诚实:relaxed 原谅的是排版,从不原谅内容——追加的页脚照样失败,也理应失败。
  5. 重测两条路径,然后重新扫描。 两条路由现在都应显示 dkim=passd= 是你的域名,扫描报告也应干干净净。

我该不该用 l= 标签让 DKIM 忽略追加的内容?

不该——并且要警惕任何建议这么做的指南。l= 标签只对正文的前 N 个字节做哈希,于是追加的页脚不再破坏签名。它的“有效”是靠让你邮件的结尾不被签名:任何人拿到一封合法签名的邮件,都能在后面追加任意内容,而你的有效签名对结果照样验证通过。这是披着修复外衣的伪造漏洞——实际滥用已被演示过,一些接收方正因如此对 l= 扣分或直接无视。解决改动本身;别把你的邮件签一半。

那邮件列表呢——能修吗?

多半不能——知道这一点能给你省下几周。会加主题标签或页脚的列表,破坏你的正文哈希是设计使然,而列表不归你管。有两件事帮得上忙:

转发是相邻的情形——它必然破坏 SPF,但只是偶尔破坏 DKIM,这正是当正文幸存时,对齐的 DKIM 是你抗转发的那条腿:见转发的邮件 SPF 失败——为什么你修不了

完整配齐的域名这么少,DKIM 为什么还这么容易坏?

因为 DKIM 是三件套里脆弱的中间孩子:SPF 是一条静态 DNS 记录,DMARC 是一份策略声明,而 DKIM 必须活着走完旅程。根据 Defaults.Exposed 普查,只有 51.84% 的已评分域名在 DNS 中发布了可发现的 DKIM 密钥,而在 261,086,232 个已评分域名中,只有 10,092,481 个——3.87%——同时具备 SPF、DKIM 和强制执行的 DMARC 策略(SPF 采用成熟度模型拆解了这架梯子)。把这个修复做对,是跻身那 3.87% 最难的一步。

常见问题

“body hash did not verify”是不是有人在冒充我的域名的迹象? 通常不是——伪造者一般根本造不出你的 DKIM 签名,所以他们的邮件要么没有签名,要么显示 no key。正文哈希失败意味着一封确实由你的基础设施签名的邮件事后被编辑了。先查你自己的网关,再去假设攻击者。

这些邮件的 SPF 是通过的——我还安全吗? 眼下也许安全:DMARC 只需要一个对齐的通过。但只要有人转发,SPF 的通过就蒸发了;而如果它没有与你的 From 域名对齐,那它对 DMARC 从来就没算过数。在只有 3.87% 的域名配齐三件套的情况下(2026-06-29 普查,261,086,232 个域名),“一条腿瘸着”是常态——也是可修复的那种。

换成 relaxed/relaxed 规范化能解决我的免责声明问题吗? 不能。Relaxed 只容忍空白和折行的变化。追加的免责声明是内容变化,哈希必须为此失败——那是 DKIM 在正确工作。要么移签名点,要么移免责声明。

失败只发生在某一个客户的域名上。为什么? 几乎可以肯定是他们那边在修改入站邮件——某台安全设备在他们的验证器运行之前改写链接或盖横幅,或者一次内部转发重新编码了正文。把本页的诊断部分发给他们;修复在他们的网关上,不在你的 DNS 里。

把报告发给老板

如果你是在替客户或雇主修这个问题,用证据收尾。改动节点修好之后,重新运行免费扫描,把评分报告转发给企业负责人:带日期、直白语言,DKIM 和 DMARC 的状态一页看清。这正是网络保险续保和下一份供应商问卷需要的凭证——证明公司发出的邮件,如今就是送达的那封邮件。

检查你的域名 → · “DKIM signature not valid”指南 → · 修复 DKIM → · 我们如何评分 → · 仅使用汇总数据。数据在欧盟境内存储和处理。