⌘K 切换工具
EMAIL AUTH

邮件头分析器

解析邮件头并追踪投递路径。

local
message-header
§01 关于此工具

概述

每一台处理过这封邮件的邮件服务器,都会在最前面加上一个 Received 头。按顺序读下来,这些头就是投递路径:哪一台主机把消息交给了哪一台,以及在什么时候交的。再配合认证结果一起读,它们能告诉你这封消息是不是真的来自它所声称的地方。

这个工具把折行的邮件头展开,将路径重建成一份带编号、带逐跳延迟的列表,并把认证相关的那几个头单独呈现出来,这样你就不必自己在一堆噪音里去找它们。

使用方法

  1. 在你的邮件客户端里打开这封消息的原始内容或者源码。Gmail 里是 显示原始邮件(Show original);Outlook 里是 属性 → Internet 邮件头(Properties → Internet headers);Apple Mail 里是 显示 → 邮件 → 原始源码(View → Message → Raw Source)。
  2. 把从消息顶部一直到第一个空行之间的全部内容粘贴进来。正文不需要。
  3. 从上往下读逐跳列表——第 1 跳就是源头。
  4. 读它下面的认证结果。

读懂逐跳列表

每一行显示发送主机(from)、接收主机(by),以及自上一跳以来的延迟。一次正常的投递是两到五跳,在几秒钟之内完成。

方向很重要。中继是往前加而不是往后加,所以原始邮件头是最新的在前面;这里的列表被反转过,于是它按消息真实走过的方向来读。当你拿它和原始源码对照的时候,记住两者相对来说是上下颠倒的。

延迟来自每个 Received 头里的日期,而那些时间戳是由不同机器上各自独立设定的时钟写下来的。一两秒的偏差,包括负的那种,属于时钟偏差,而不是任何事情的证据。相差几分钟或者几小时才是真的,而且几乎总意味着接收服务器把这封消息排进了队列——灰名单会刻意推迟首次出现的发送方,它是最常见的那个单一原因。

读懂认证结果

有四个头是重要的,而它们回答的是不同的问题:

  • Received-SPF——连接过来的那个 IP,是否被授权代表信封发送方的域名发信?SPF 检查的是信封(MAIL FROM),那不是你收件人看到的那个 From: 头。一封消息完全可以通过 SPF,同时仍然显示一个伪造的发送方。
  • DKIM-Signature——针对选定的若干个头和正文所做的密码学签名,可以用签名域 DNS 里的公钥来验证。d= 是签名域,s= 是选择器,两者合起来就定位到密钥所在的 <selector>._domainkey.<domain>
  • Authentication-Results——接收服务器自己给出的判定,综合了 SPF、DKIM 和 DMARC。这是应该第一个去读的一行,因为它是整条链里唯一一台你有理由信任的机器写下来的。
  • ARC-Authentication-Results——某个中间方在修改这封消息之前记录下来的判定。邮件列表会按设计重写邮件头并因此破坏 DKIM,而 ARC 存在的意义就是让原始结果在那之后仍然留存下来。

DMARC 才是决定收件方实际会怎么做的那一个。它要求 SPF 或 DKIM 通过,并且还要对齐——通过的那个域名必须和可见的 From: 头里的域名一致。对齐正是一封消息可以显示 spf=passdkim=pass、却仍然 DMARC 失败的原因:两个都通过了,只不过是为了错误的那个域名。

示例

  • 「我们的邮件都进垃圾箱。」 读一封你自己发到另一个服务商邮箱的消息上的 Authentication-Results。如果 DKIM 通过而 DMARC 失败,那么问题出在对齐上,不在签名上。
  • 一封很像真的钓鱼邮件。 拿第 1 跳上的 from 和可见的 From: 头里的域名对比。伪造一个显示名是轻而易举的事;而伪造出一个跟所声称域名的真实基础设施相符的首跳,就不是了。
  • 一封要二十分钟才送到的邮件。 找出延迟所在的那一跳。如果它是收件方的第一台入站服务器,灰名单是最可能的答案,而且它会在重试时自行解决。
  • 一次 DNS 变更之后邮件不再送达。 检查结果里的 SPF。同一个域名上有两条 SPF 记录,或者一条记录超过了十次查找的上限,两者都会产生一个看起来像谜团的永久失败。
  • 邮件列表破坏了你的签名。 找 ARC 头。它们的存在告诉你,有一个中间方修改过这封消息,并且把更早的那个判定记录了下来。

说明

续行会在解析之前被展开。很长的邮件头会跨多行折叠,续行以空白字符开头,而一个逐行读取、不做拼接的解析器,恰好会把最重要的那几个头截断。

fromby 的值只从子句的开头读取。一个没有 from 子句的 Received 头,往往仍然在某个注释里含有 envelope-from 这个字符串,而把那个当成连接主机,就会把一个由攻击者提供的地址显示成这封消息的源头——而那恰恰就是你来这里要核对的那个事实。

这里的一切描述的都是邮件头说了什么。在你控制的第一台机器之前写下的那些头可以被整段伪造,所以这条链是关于你自己基础设施的证据,而只是关于上游一切的一个声称。

如果你要检查的是一封保存下来的消息本身,而不只是它的邮件头,请用 EML 查看器

FAQ
我粘贴的邮件头会被上传到什么地方吗?
不会。邮件头在页面内展开折行并完成解析,没有任何网络请求。这一点在这里很重要,因为完整的邮件头里包含收件人地址、内网主机名和消息 id。
为什么逐跳列表的顺序和原始邮件头是相反的?
因为每一个中继都把自己的 Received 行加在最前面,所以原始顺序是最新的在最上面。这个列表被反转过,于是第 1 跳是最初的发送方,最后一跳是你的邮箱——也就是这封消息真实走过的方向。
最早的那几跳可信吗?
只有从你自己控制的第一台服务器往内的部分可信。在那之前的一切都是由你并不运维的机器写下的,可以被整段伪造。请从下往上读这条链,读到你自己基础设施的边界就停止信任。
某一跳的发送主机显示成一个短横,这有问题吗?
没有问题。内部中继常常只记录一个 `by` 子句而不带 `from`,这对本地投递、LMTP 交接和 sieve 过滤来说都是正常的。短横意味着这个头确实没有 from 子句,而不是解析失败了。
某一跳延迟很长意味着什么?
通常是灰名单,或者接收服务器上有队列。延迟是从相邻两个 Received 头里的时间戳算出来的,而那些时钟属于不同的机器,所以一个小的负值或者零延迟是时钟偏差,不是时间旅行。