SPF、DKIM与DMARC详解:邮件发件人验证是如何运作的

曾几何时,任何人都能伪造邮件的"发件人"地址——这里讲清楚SPF、DKIM和DMARC是如何联手让这件事变得困难得多的。

邮件发件人伪造(欺骗)问题

SMTP是邮件收发所依赖的基础协议,它本身从来没有设计过验证发件人地址的机制。这意味着任何人都可以在"发件人"一栏原样填上某家银行或公司的地址,这也长期以来成为钓鱼邮件的根本基础。

SPF:发件服务器白名单

SPF(发件人策略框架)让域名所有者在DNS的TXT记录中登记"可以代表这个域名发送邮件的服务器列表"。收件服务器会检查实际发送邮件的服务器IP是否在这份列表中,以此来判断该邮件是否可能是伪造的。

DKIM:用数字签名检测篡改

DKIM(域名密钥识别邮件)在发送邮件时,用发件域名的私钥对邮件正文和部分主要邮件头进行签名,并将签名附加到邮件头中。收件服务器用DNS中公开的公钥验证这个签名,从而确认邮件内容自发出后是否被篡改过。

DMARC:综合结果制定策略

DMARC(基于域名的消息认证、报告与一致性)在SPF和DKIM检查结果的基础上,还会进一步核实实际显示的发件人地址是否与用于验证的域名一致(即"对齐")。域名所有者可以自行指定策略,决定验证失败的邮件是照常投递(none)、投入垃圾邮件(quarantine),还是直接拒收(reject),还能收到汇总验证失败情况的报告。

三种技术之间的关系

SPF和DKIM各自都是独立运作的认证手段,而DMARC则是位于两者之上的策略层,综合它们的结果来指示"验证失败时该如何处理"。只有三者同时具备,防止邮件伪造的效果才能真正发挥出来。

如何在收到的邮件中查看验证结果

打开邮件的原始邮件头,会看到一个名为"Authentication-Results"的字段,显示spf=pass、dkim=pass、dmarc=pass这样各项检查的结果。如果这些值显示为fail或none,就有必要重新怀疑一下这封邮件是否真的来自它所声称的发件人。

SPF的“10次查询”上限与常见配置错误

SPF规范(RFC 7208)规定,include、a、mx、exists、redirect这类需要额外DNS查询的机制,累计不得超过10次。一旦超过,收件方会返回permerror(永久性错误),在DMARC判断中等同于SPF失败。直接写ip4、ip6地址的机制不计入次数。每接入一个云服务就往SPF里加一条include,很容易触顶,所以不再使用的发信服务要及时删除。另一个典型错误是在同一个域名下发布多条以v=spf1开头的TXT记录,必须合并成一条。结尾的~all(软失败)表示“列表之外的来源可疑”,-all(硬失败)表示“列表之外的来源不合法”,两者表达的态度强度不同。

DKIM的选择器与密钥长度

DKIM的公钥发布在“选择器._domainkey.域名”这条DNS记录中。选择器相当于密钥的名称,不同的邮件服务或不同代际的密钥可以使用不同的选择器,因此多个服务用同一个域名发信也不会互相冲突。关于密钥长度,RFC 8301要求签名方至少使用1024位RSA密钥,并建议使用2048位及以上,新生成的密钥通常直接选2048位。过长的密钥可能放不进单条DNS记录,需要拆分登记,所以要先确认DNS管理后台的支持情况。定期换用新的选择器(密钥轮换)是更稳妥的运维做法。

对齐(Alignment):宽松与严格

DMARC真正关心的是:收件人看到的“发件人”(From头)域名,与验证所用的域名是否一致。对SPF来说比较的是信封发件人(Return-Path)的域名,对DKIM来说比较的是签名中的d=域名,只要其中任意一项既通过验证又保持一致,DMARC就判定为通过。一致性有宽松(relaxed,同一组织域名下的子域名差异可以接受)和严格(strict,必须完全相同)两种模式,默认是宽松。如果第三方群发服务使用自己的域名作为Return-Path,SPF虽然通过,但不会与你的From域名对齐,常见的解决办法是让该服务用你自己的域名做DKIM签名。

为什么转发和邮件列表会破坏验证

邮件被自动转发到另一个地址后,实际发信的IP变成了转发服务器,原域名的SPF验证就会失败。DKIM签名只要正文和被签名的头部没有被修改,转发后依然有效,所以DMARC仍可借助DKIM通过。但邮件列表常常会在主题前加标签或在末尾追加页脚,改动内容后签名就失效了。为应对这类中转场景,业界提出了ARC机制(RFC 8617),中转服务器可以附上一条“我收到时验证是通过的”的记录,不过收件方是否采信,取决于各自的策略。

DMARC报告能告诉你什么

在DMARC记录的rua标签中填写接收地址,各大邮箱服务商就会发来汇总报告(XML格式,通常按天)。报告里有以你的域名名义发出的邮件的来源IP、数量、SPF与DKIM的验证结果以及被采取的处理策略。通过它,你既能发现自己没留意到的合法发信方(比如营销工具或老旧服务器),也能看到有人尝试冒用域名。rua之外还有ruf标签用于逐封的失败样本报告,但愿意提供的服务商有限,还涉及隐私问题。XML不方便直接阅读,不少组织会借助免费的报告解析服务。

大批量发信方的要求(2024年起)

自2024年2月起,Google与Yahoo要求大批量发送邮件的发信方同时配置SPF和DKIM,至少发布p=none的DMARC记录,为营销类邮件提供一键退订(RFC 8058),并把垃圾邮件投诉率控制在较低水平。对Google而言,向个人Gmail地址每天发送约5000封以上通常被视为大批量发信方的门槛。这些条件和具体数值可能被各家更新,发送量较大的组织请以官方最新文档为准。

为什么三项检查缺一不可

仅靠SPF,攻击者仍可以从域名授权列表中的服务器发送邮件,同时伪造显示名称来绕过检测;仅靠DKIM,也无法验证显示出来的"发件人"地址是否与签名域名一致。DMARC通过要求显示发件人与实际通过SPF或DKIM验证的域名保持一致,填补了这个漏洞。这正是注重安全的组织不满足于只用其中一项、而要把三者组合配置起来的原因。

配置不当的严格DMARC策略会付出什么代价

如果在还没有把第三方营销工具、CRM系统等所有合法发件来源正确授权之前,就把DMARC策略过于激进地设为拒绝(reject),可能会导致本组织自己的合法邮件被其他邮件服务器悄无声息地拒收。多数组织通常会先从"none"(不采取行动)策略开始,收集报告以确认所有合法发件来源都已被识别,然后再逐步过渡到隔离(quarantine),最终升级到拒收(reject)。

落地顺序:不要一上来就设成reject

实际操作中通常按下面的顺序推进。先盘点所有在用的发信来源(自有服务器、群发平台、工单系统、发票系统等)并登记到SPF;再在每个服务中启用DKIM签名,并让签名域名与自己的域名一致;然后发布p=none加rua,收集几周的报告,确认没有合法来源验证失败后,再升到quarantine,一切稳定后才考虑reject。如果希望子域名适用不同策略,可以使用sp标签。检查记录可以用nslookup或dig查询TXT记录,也可以使用免费的在线检测站点。

验证通过不等于邮件可信

SPF、DKIM、DMARC能证明的只是“发信方有权使用这个域名”,并不判断邮件内容是否安全。如果攻击者自己注册了一个长得很像的域名(比如替换了一个字母),从这个域名发出的邮件完全可以通过它自己的验证;被盗用的正规账号发出的邮件同样能通过验证。换句话说,这些技术防的是对域名的直接冒用,而相似域名、内容诈骗仍需要用户自己留意,比如核对链接指向的域名,并通过另一条渠道向对方求证。

常见问题

SPF验证通过,是否就能确定这封邮件一定是真实的?

不能仅凭这一点判断。SPF只能确认发件服务器是否获得了该域名的授权,并不能验证显示的"发件人"地址是否一致,也无法确认内容在传输过程中是否被篡改过。DKIM和DMARC正是用来弥补这些缺口的,所以这三者通常需要配合使用。

明明是合法邮件,为什么DMARC验证还会失败?

这种情况常见于通过第三方服务(比如营销平台或工单系统)发送邮件,却没有把该服务正确添加到域名的SPF记录中,或者没有为其配置专属的DKIM签名。负责管理某个域名邮件系统的人,需要把所有合法的发件来源都纳入授权范围,而不只是自己的邮件服务器。

怎么确认自己域名的配置是否正确?

最基本的办法是直接查询TXT记录:SPF查域名本身,DMARC查_dmarc.域名,DKIM查选择器._domainkey.域名,可用nslookup或dig。更可靠的做法是用自己的域名给Gmail等邮箱发一封测试邮件,查看“显示原始邮件”中的Authentication-Results,确认spf=pass、dkim=pass、dmarc=pass。

个人域名发信量很小,也需要配置吗?

建议配置。没有SPF和DKIM的邮件更容易被判为垃圾邮件;发布了DMARC之后,别人冒用你的域名发出的邮件也更容易被收件方拒收。可以先从p=none开始,边看报告边调整,这样误伤合法邮件的风险较小。