SPF邮件防伪全解析:原理、配置与常见坑 1. 邮件伪造到底是怎么回事1.1 一封看起来完全正常的邮件可能不是你想的那个人发的大家应该都有过这种经历——收到一封显示“来自某银行”的邮件抬头有正规的Logo发件人名字也是熟悉的客服热线点开链接要你输入账号密码仔细一看网址是个完全陌生的域名。这套路不新鲜但中招的人依然不少。我见过很多企事业单位做安全培训最喜欢拿这种钓鱼邮件当典型案例而大多数钓鱼邮件的源头就建立在邮件伪造的基础上。邮件伪造Email Spoofing说白了就是攻击者让一封邮件看起来像来自某个他并没有控制权的地址。SMTP协议最初的设计目的是让邮件顺利送达它默认信任发件人几乎不做什么身份校验。你用任何一款邮件客户端或者干脆用命令行敲几句SMTP指令就能把“From:”字段写成一串完全不属于你的地址。接收方服务器和邮件客户端绝大多数情况下都会乖乖把这个地址展示给收件人于是“伪造”就这样生效了。早期互联网圈子里大家都很“淳朴”默认使用邮件的人都是诚实的所以协议层面留了很大的信任空间。等垃圾邮件、钓鱼邮件泛滥成灾之后业界才意识到必须补上这个漏洞。于是就有了SPFSender Policy Framework发件人策略框架这套机制。它要解决的核心问题就一句话如何判断一封声称来自某域名的邮件真的是该域名授权发出的邮件。1.2 伪造邮件的三个典型套路我把常见的伪造手法归纳了一下方便大家理解SPF到底在防什么。直接伪造From地址用Outlook、Foxmail或者Python写个SMTP脚本把发件人随便填成adminyour-bank.com大部分小邮件服务器根本不会管你。这种是最low的同时也是最管用的因为人眼很难在密密麻麻的邮件列表里盯着域名看。相似域名迷惑不伪造完全一样的域名而是注册一个长得几乎一模一样的域名比如把o换成0把l换成1或者加个点。收件人一不留意就点进去了。SPF对这种情况其实帮不上太多忙因为攻击者用的是自己的域名SPF检验会通过。利用重定向和转发链邮件经过多个服务器中转发件人字段被层层传递某些配置松散的服务器不校验原始来源就给了可乘之机。转发邮件是SPF天然的坑后面会细说。1.3 一封伪造邮件的完整传播链路拿一个最简单的手工伪造来演示一下大家就明白为什么纯靠服务器默认配置拦不住了。假设攻击者想伪造servicepaypal.com给你的victimexample.com发信他只要手动连接目标邮件服务器的25端口然后输入下面这些指令EHLO attacker.com MAIL FROM: servicepaypal.com RCPT TO: victimexample.com DATA Subject: Your account has been suspended Please log in to restore your account: http://fake-link... . QUIT你看这段“对话”里没有一个环节要求攻击者证明自己确实拥有paypal.com的控制权。目标服务器如果本身没有做发件人身份校验它就会把这封邮件收下来投递到victim的收件箱。收件人的邮件客户端看到servicepaypal.com直接显示发件名是“PayPal”信任度一下子就上来了。所以邮件伪造的本质在于SMTP协议只保证发送过程的可靠性不保证发件人身份的真实性。你要对付它就不能指望服务器自觉必须在协议之外加一道身份验证机制。SPF就是最早被广泛采用的那道防线。2. SPF的核心机制与工作原理2.1 SPF机制到底是什么这里要专门回应一下网上搜到的“SPF模型”这个词。其实不是新出的什么机器学习模型大家把SPFSender Policy Framework音译或直译成“发件人策略框架”也有人叫它“SPF模型”本质上指的就是一套基于DNS的邮件发送方授权校验规则。它的思路非常朴素域名所有者在自己的DNS里发布一条TXT记录列明“这个域名的邮件比如由哪些IP或服务器来发”。收件方收到邮件后反查发件人域名的TXT记录看看这封邮件的实际来源IP在不在白名单里。在就放行不在就按规则执行失败/软失败/中立等不同策略。一个人要证明“我是我”最方便的方式是拿身份证明给查验方看。SPF相当于让域名所有者提前在“通讯录”DNS里声明了自己授权了哪些发件人。收件方收到邮件后在这个通讯录里对一下笔迹真实身份自然水落石出。2.2 一条完整的SPF记录长什么样我们在DNS管理后台里常见的SPF记录形式是这样vspf1 ip4:192.0.2.10 ip4:192.0.2.20 include:_spf.example.net -all拆开看它由几个部分组成vspf1版本标识告诉解析方这是一条SPF记录。ip4:192.0.2.10明确允许某个IPv4地址发信。ip4:192.0.2.20再允许一个。include:_spf.example.net引入另一个域名的SPF规则用于把多个服务商比如第三方邮件营销平台的发信IP包含进来。-all最终兜底策略代表“所有未匹配上述规则的发信IP都判定为失败”。SPF记录中还有一些常见机制我列个表方便大家对照机制写法示例含义允许指定IPip4:203.0.113.5/ip6:2001:db8::/32该IP发的信合法允许指定域名A记录a:mail.example.com该域名解析出的IP合法允许指定域名MX记录mx:example.com该域名的MX服务器IP合法包含其他域名的SPFinclude:spf.thirdparty.com递归引入其他域的SPF规则所有发信域名exists:user.example.com按解释结果决定匹配与否较少用限定范围ptr:example.com反向解析校验不推荐容易出问题结果修饰符~all/-all/all软失败 / 硬失败 / 全部放行~all和-all的区别大家一定要搞懂。~all是“软失败”意思是“我不确定但大概率不合法”很多收件方看到软失败仍然会收下邮件只是可能标记为垃圾邮件。-all是“硬失败”意思是“没匹配上就直接拒收”。从安全角度讲能上-all就不要用~all前提是你确保已经把所有正规发信通道都写进include了。2.3 收件方是如何一步步检查SPF的当一封声称来自example.com的邮件到达收件方的邮件服务器比如Gmail、Outlook的服务器它会先提取信封发件人MAIL FROM不是邮件头里那个展示用的From地址。然后做这些事根据信封发件人的域名去DNS查询该域名的SPF TXT记录。如果查不到或者格式错误permerror则SPF结果直接判定为none或permerror。如果查到了就按顺序解析SPF文本中的各个机制直到遇到一个匹配项或者走到最后的all。根据匹配结果和all修饰符生成最终判定pass、fail、softfail、neutral、permerror、temperror。把判定结果交给反垃圾邮件系统结合域名信誉、内容特征等综合打分决定邮件是进收件箱、垃圾箱还是直接拒收。这里有一个重要的点SPF检查的是“信封发件人”而不是用户在邮件客户端看到的“展示发件人”。很多邮件伪造恰恰利用了这个区别——信封发件人和展示发件人不一样SPF可以通过但用户看到的却是伪造的展示名。这也是后来需要DMARC的原因之一我们留到后面第五节聊。2.4 SPF的解析规则踩坑点SPF看起来简单但实现起来有不少细节容易踩坑我挑几个实战中最常见的讲DNS查询次数限制。SPF协议规定一次完整的SPF解析最多只能进行10次DNS查询。这10次里包括include、a、mx、ptr机制带来的查询次数。include嵌套过多、a和mx引用的域名每次都解析新的IP这些都是算次数的。一旦超过10次结果直接变成permerror等于没设。我见过有公司把四五个第三方平台的include一股脑堆进去还没数结果SPF一直不生效排查半天才发现是超限了。记录长度的坑。DNS的TXT记录单条长度不能超过255个字符超过之后最好拆分成多条字符串拼接。大多数DNS服务商面板有自动校验但如果你用命令行工具直接改区域文件就要格外小心。SPF记录的推荐上限是512字节超过以后老旧的DNS中间设备可能会处理异常。大小写和空格。SPF记录对大小写不敏感但空格和分隔符必须准确漏一个空格解析器可能直接把整条记录判为格式错误。我在维护阶段吃过一次亏改完记录后明明看着没错dig一查原来是写成了vspf1 ip4:1.2.3.4include:...中间少了空格导致permerror。3. 手把手配置SPFDNS记录实操指南3.1 配置前需要先理清发信通道很多人一上来就在DNS后台粘贴一条SPF记录结果配完发现邮件照样进垃圾箱。原因往往是没想清楚自己到底有哪些发信出口。配置SPF之前我建议你先梳理这张清单自建邮件服务器或公司域名的邮件收发服务器它们的公网IP是什么是否用了第三方企业邮箱服务比如腾讯企业邮、阿里企业邮、Google Workspace、Microsoft 365它们通常都会在自己的帮助文档里明确给出需要include的SPF记录值。是否使用邮件营销平台或通知类服务发送工单邮件、验证码邮件这类服务一般都会在后台的“域名验证”页面告诉你应添加的SPF记录并且大多使用include方式。是否有独立部署的邮件网关、中继服务器或防病毒网关它们的出口IP也要加进来。把这张表列出来再去看自己现有的SPF记录基本上就知道该怎么补齐了。宁可多配一两个IP也不要漏掉正规发信通道不然加了-all之后误杀自己人比被伪造还难受。3.2 以常见的DNS服务商为例完整配置流程我拿一个比较典型的场景演示一家公司用自己的域名example.com收发邮件邮件服务器部署在云主机上公网IP是203.0.113.66同时用了第三方邮件营销平台发送Newsletter。那么SPF记录可以配置为vspf1 ip4:203.0.113.66 include:send.grid.net -all具体操作步骤登录你的域名DNS管理后台找到example.com的解析记录列表。添加一条类型为TXT的记录主机记录填代表根域名也有的控制台写为空。在TXT值那一栏填入上面这串内容。保存后等待DNS生效通常几分钟到几小时不等取决于TTL和各级DNS缓存。用dig TXT example.com或在线SPF查询工具验证记录已经能读到并且语法正确。如果你用的是第三方企业邮一般会有现成的SPF建议拿腾讯企业邮举例它的文档里直接写了这样一条vspf1 include:spf.mail.qq.com ~all这种你就别去猜测它背后的IP有哪些直接把include段照抄就行。第三方平台更新出问题的话它自己会调整spf.mail.qq.com这个子域名的SPF记录你的主域名记录不用动。这就是include设计的意义——把子域的SPF记录当作一个可动态更新的“名单”可以解耦维护。3.3 用命令行工具验证配置是否生效配置完最忌讳的就是“觉得配好了”。我一般会先在自己电脑上跑两条命令确认dig TXT example.com重点关注输出里的TXT记录值看是否和自己在DNS后台填的一致。接着用以下命令检查SPF记录的语法是否合规nslookup -typeTXT example.com或者更直观一点用spfquery工具如果有spfquery -m fromexample.com -s 203.0.113.66 -helo mail.example.com如果返回pass就说明这条SPF记录已经能正常工作了。没有spfquery的环境也没关系现在很多在线工具比如帮助文档常推荐的那些SPF lookup和debug工具输入域名就能帮你把整条记录从头到尾解析一遍包括include链、DNS查询次数、每个机制的匹配结果排查效率比手工看高很多。还有一个容易被忽略的点记录生效后不要急着删掉旧的SPF记录。DNS里同一主机名下如果存在多条TXT记录收件方解析时可能会随机取到其中一条导致结果不稳定。正确做法是把新旧内容合并成一条完整的SPF记录替换掉旧条目而不是同时保留两条。3.4 一个完整的SPF配置实例假设我有一个域名blogtest.cn自建了一套基于PostfixDovecot的邮件系统同时接了阿里云企业邮来收发日常邮件另外还在用SendCloud这类平台发系统通知邮件。那我可能会这样配置vspf1 ip4:123.123.123.123 include:spf.qiye.aliyun.com include:spf.sendcloud.net -all其中123.123.123.123是我自己邮件服务器的公网IP两个include分别引入企业邮箱和第三方通知平台的SPF规则最后用-all严格兜底。这样真实发信IP能匹配上的就放行其余一律判失败。如果你不确定自己的场景该用~all还是-all我建议刚上线时先用~all跑一两周看有没有正常业务邮件被误判。确认没有遗漏发信通道后再改成-all。3.5 配置过程中的注意事项小结配置SPF这件事看着就是加一条解析记录但实际操作中我一定反复检查这几点主机记录写的是还是子域名如果是给子域名配置SPF主机记录就写对应的子域名前缀。确认记录类型是TXT不是MX也不是SPF类型。老一些的DNS系统曾有SPF类型记录但如今统一用TXT记录不要混淆。检查include链是否闭合。如果include了一个不存在的子域名解析会直接permerror整条SPF失效。检查是否有空格丢失、逗号误用、协议版本标识写错。检查发信通道是否齐全特别是营销平台、客服系统、工单系统这些最容易漏。4. 常见问题与排查技巧实录4.1 为什么配了SPF还是会被伪造/被判失败遇到“SPF配了但邮件还是被拒收”这类问题先别急着怀疑记录写错。我整理了一份排查清单按优先级从高到低排列DNS缓存未刷新刚改完记录全球DNS缓存更新需要时间。可以用在线工具从不同地区节点查询确认全球一致性。记录语法错误用SPF校验工具跑一遍看有没有permerror、include循环、查询次数超限。发件服务器IP没有匹配上邮件服务器可能有多个出口IP特别是云服务器帮用户做了NAT出口转换的时候实际出口IP可能和配置的IP不一致。查看邮件头里的Received: from字段找到实际发送IP然后对比。邮件经过转发当邮件经过一个转发服务器时原始SPF通常是针对原始发件域的转发服务器IP并不在原始域的SPF白名单里就会变成fail。这是SPF先天的短板。信封发件人和发件域不一致不少程序在调用SMTP发送时没有正确设置MAIL FROM导致SPF查询的域名跟展示的From域名不一致看起来像是伪造其实是发件端配置错误。4.2 转发邮件场景下SPF为什么会失效转发是邮件体系中特别容易踩雷的场景。举个例子你原来的邮件发到旧邮箱AA设置了自动转发到新邮箱B。邮件到了A的服务器后A再把它原样发给B。此时邮件头的信封发件人还是原始发件人域。B收到后检查SPF查询的是原始发件人域的SPF记录而在A服务器的转发过程中实际投递IP成了A服务器的IP。这个IP大概率不在原始域名的SPF白名单里于是SPF检查变成fail。解决转发场景有几种思路让转发服务器先进收件箱再通过规则转发而不是直接SMTP转发。在原始域的SPF记录里加入转发服务器的IP但这等于把发信权限开放给第三方一般不建议。在转发服务器上使用SRSSender Rewriting Scheme重写信封发件人。SRS会把MAIL FROM改写成自己的域从而让SPF检查通过。不少专业邮件网关已经内置了这个功能。4.3 几个常见SPF结果的含义收件方邮件服务器计算完SPF之后会输出一个结果里面常见的有pass、fail、softfail、neutral、none、permerror、temperror。我经常看到有人把“softfail”当成“失败”其实不是。下表把这些结果解释清楚结果含义通常处理方式pass发件IP在SPF记录允许名单内正常收信fail也就是-发件IP不在允许名单内且策略为-all一般直接拒收或丢弃softfail也就是~不在名单内但策略为~all继续收信但可能会被打入垃圾箱或增加垃圾邮件评分neutral策略为?all未明确允许但也不拒绝按中性处理不参与判定none域名没有发布SPF记录无法校验不直接拒收permerrorSPF记录语法错误、DNS查询超限等通常按未通过处理temperror临时解析故障可能重试或延迟退信4.4 排查案例一次典型的SPF误判我之前帮一个客户排查过邮件退信问题现象是客户公司发出去的邮件收件方那边偶尔提示“SPF fail”。查了一圈发现客户的邮件服务器有两个网卡分别是内网IP和外网IPPostfix的mynetworks设置里把内网IP也放进了发信源但出口经过路由器NAT后发给外部的IP是公网IP这个公网IP在SPF记录里确实加了。可问题是当时有另一个备用线路故障切换后出口IP变了SPF记录里没加那个备用的IP导致部分邮件fail。后来我把备用IP也加进SPF记录并把两条线路的IP都做了白名单问题才彻底解决。所以这里想提醒大家云服务器或多线路接入的场景一定要把云厂商的出口IP段、备用线路IP段都考虑进去。有些云服务商提供了专门的SPF记录值可以直接include。4.5 SPF和DKIM、DMARC的关系经常有人问是不是配了SPF就万事大吉答案是还不够。SPF只验证信封发件人的IP权限它无法验证邮件内容是否被篡改也无法防止展示地址伪造。这时候就得请出两位队友DKIMDomainKeys Identified Mail通过数字签名验证邮件在传输过程中是否被篡改同时也能证明这封邮件确实由该域名签发。DKIM的验签结果是SPF之外的另一重身份绑定。DMARCDomain-based Message Authentication, Reporting, and Conformance定义了如果SPF和DKIM都失败收件方该怎么处理邮件并要求域名所有者提供接收报告。DMARC把SPF和DKIM的结果绑定到展示地址域名上能有效阻止直接伪造From地址的钓鱼邮件。要构建完整的邮件防伪体系SPF、DKIM、DMARC三者缺一不可。SPF管“谁有资格发”DKIM管“内容有没有被动过”DMARC管“失败了怎么处置”。我见过很多公司只配了SPF结果以为安全了实际钓鱼邮件一封都没少——因为攻击者可以绕过SPF校验只改展示地址。4.6 一份快速自检清单如果你正遇到SPF相关的问题可以直接按这份清单过一遍确定收件方查询的域名是信封发件人域不是你展示的From域。用SPF校验工具检查DNS记录语法和include链是否正常。查看真实发件IP是否在SPF允许列表内注意是否有多个出口。确认是否配置了-all或~all以及是否符合你的容错需求。检查DNS记录是多条TXT还是合并成了一条避免系统随机取用。如果是转发场景判断是否引入了SRS机制否则SPF失败在所难免。最后结合DKIM、DMARC做整体评估不要单看SPF结果。5. 从实操角度聊聊SPF的选型和演化5.1 到底用~all还是-all这个问题没有标准答案完全看业务容错能力。电商平台、银行、政务邮箱这类对安全要求极高的系统必须用-all即使偶尔误杀一封邮件也比被仿冒一次危害小得多。初创公司、个人博主、非关键业务邮箱建议先用~all过渡一段时间观察是否有正常邮件被判定为softfail再逐步收紧成-all。我个人的习惯是分阶段第一阶段不设SPF或先用~all同时把发信通道梳理清楚。第二阶段批量测试所有发信通道的IP和include确保没有遗漏。第三阶段切换成-all同时监控邮件退信率和DMARC报告中的fail数据。第四阶段定期复查DNS记录跟进第三方平台SPF子域的变化。5.2 关于“spf模型”这个说法的澄清现在搜索引擎里“spf模型”这个热度词出现得比较频繁部分原因是很多技术博客和SEO文章在写邮件安全时会把它写成“SPF模型”。需要明确的是这个名字和机器学习里的生成模型、判别模型完全没关系。在网络协议领域SPF就是Sender Policy Framework本质上是一套基于授权IP列表的校验策略。你有时看到博客把SPF叫做“SPF模型”通常只是指这套“策略框架”的实现模型而非某种新的AI架构。理解这一点能帮你避免被乱七八糟的热词带偏方向。5.3 SPF不是万能的但缺了它万万不能从2014年SPF正式成为RFC 7208标准到现在十年过去了垃圾邮件和钓鱼邮件的比例依然居高不下。为什么因为SPF解决的只是“发件人IP是否被授权”它不能面面俱到对相似域名仿冒无能为力因为攻击者用的是自己的域名。对子域名仿冒有局限如果攻击者注册了foo.example.com你的域名下实际不存在的子域名而你的SPF只发布在根域某些收件方配置不严谨时依然可能放行。对邮箱账号接管攻击帮助有限如果攻击者破解了合法账号密码他就可以通过合法IP发信SPF自然判定pass。但这不意味着SPF没有价值。今天主流邮箱服务商包括Gmail、Outlook、企业微信、钉钉已经全面把SPF作为反垃圾和反钓鱼的基础打分项。没有SPF记录的域名信誉度天然低人一等不仅容易被标记为垃圾邮件还可能在DMARC策略里直接被拒收。在搭建邮件系统的第一步就把SPF配置好是投入产出比极高的一件安全基建工作。6. 我的一些实操体会这行做久了我越来越觉得邮件安全像盖房子SPF是地基DKIM是墙体DMARC是屋顶防水层。地基不牢后面再豪华的装潢也白搭。我自己维护的几个域名里曾经因为漏加了一个第三方营销平台的include导致营销邮件大面积进垃圾箱当时还以为是内容触发了反垃圾规则排查了大半天才发现是SPF在拖后腿。顺手分享一个能少走弯路的小技巧每次更换邮件服务商或者新增发信通道时第一时间在SPF记录里加好对应的include同时把变更记录写下来。很多公司半年一年不去动DNS一旦动起来就乱成一锅粥就是因为没有维护清单。我习惯在配置文档里专门开一小节记录“当前SPF包含哪些发信通道、对应哪个业务系统、何时添加”下次改的时候照着清单核对基本不会漏。如果你正在被邮件伪造或者发信率问题困扰可以先把SPF配好再看看DKIM和DMARC三层都到位之后邮件系统的信任度会有一个质的提升。另外提醒一句互联网上关于“SPF模型”的零散说法很多建议直接以RFC 7208和相关服务商的官方文档为准少走弯路。最后再强调一次安全没有一劳永逸。SPF配置完之后记得定期复查、关注DMARC报告、留意第三方平台发的变更通知。邮件伪造的道具很多但至少把门锁换好别用一把能轻易捅开的钥匙。