邮箱网 0条评论 6125次浏览 2022年03月23日 星期三 10:24
一、SPF,全称Sender Policy Framework,即发件人策略框架。
SPF是为了防范伪造发件人地址发送垃圾邮件而提出的一种开放式标准,是一种以IP地址认证电子邮件发件人身份的技术。域名所有者通过在DNS中发布SPF记录来授权合法使用该域名发送邮件的IP地址。
当在DNS中定义了域名的SPF记录后,为了确认邮件声称发件人不是伪造的,邮件接收方首先检查邮件域名的SPF记录,来确定发件人的IP地址是否被包含在SPF记录中,若包含,则认为是一封正确的邮件,否则认为是一封伪造的邮件并退回,或将其标记为垃圾/仿冒邮件。
设置正确的SPF记录可以提高邮件系统发送外域邮件的成功率,也可以一定程度上防止被假冒域名发送邮件。
例子:qq.com的spf记录
qq.com text = "v=spf1 include:spf.mail.qq.com ~all"
二、SPF记录的语法
SPF记录是由SPF版本和指定的IP组成。
SPF记录由一个版本开始,格式为:
record = version terms *SP
version = "v=spf1"
terms 由机制mechanisms和修改符modifiers(可选的)组成。
域名定义了一个或者多个机制mechanisms,用来描述哪些IP是被允许使用该域名发送邮件。
Mechanisms包含以下几种类型:
mechanism = ( all / include/ a / mx / ptr / ip4 / ip6 / exists )
域名可能也定义修改符modifiers,每个修改符只能使用一次。
Modifiers包含以下几种类型:
modifier = redirect / explanation
(一)机制mechanisms
每个mechanism有四种前缀(默认前缀为“+”):
在一条SPF记录中,从左到右依次对每个mechanism进行验证。对一个mechanism进行检测,有三种结果可能发生:IP匹配成功,IP匹配失败或者返回异常。如果IP匹配成功,处理结果返回该mechanism的前缀;如果IP匹配失败,继续下一个mechanism;如果返回异常,则mechanism结束并返回该异常值;如果没有mechanism或者modifier匹配,则结果返回“Neutral”。
"+"
Pass
"-"
Fail
"~"
SoftFail
"?"
Neutral
如果不存在SPF记录,则返回“None”;如果在DNS解析过程中出现临时性错误,则返回“TempError”;如果存在某些语法错误或者评估错误(如该域指向不为人知的机制),则返回“PermError”。
SPF记录验证可能返回的结果如下:
Result
Explanation
Intended action
Pass
SPF记录验证该发信IP为合法的
接收邮件
Fail
SPF记录验证该发信IP是不合法的
拒绝邮件
SoftFail
SPF验证该发信IP不是合法的,但是不采取强制措施
接收邮件但作标识
Neutral
SPF记录没有明确说明发信IP是否合法的信息
接收邮件
None
域名没有设置SPF记录或者SPF记录验证没有结果
接收邮件
PermError
发生永久性错误(如:SPF记录格式错误)
没有规定
TempError
发生临时性错误
接收邮件或拒绝邮件
1、“all”机制
“all”表示所有IP都匹配。通常放在SPF记录末尾,表示处理剩下的所有情况。
例如:
"v=spf1 mx -all" 表示允许所有该域的MX邮件服务器发送邮件,禁止其他的。
"v=spf1 -all" 表示该域不会发送任何邮件。
"v=spf1 +all" 表示域名所有者认为SPF是没有用的或者并不关心(任何服务器都可使用该域名发送邮件)。
2、“ip4”机制
格式为:
ip4:<ip4-address>
ip4:<ip4-network>/<prefix-length>
如果没有提供 prefix-length ,默认为 /32。
例如:
"v=spf1 ip4:192.168.0.1/16 -all"
表示只允许192.168.0.1~192.168.255.255范围内的IP地址。
3、“ip6”机制
格式为:
ip6:<ip6-address>
ip6:<ip6-network>/<prefix-length>
如果没有提供 prefix-length ,默认为 /128 。
例如:
"v=spf1 ip6:1080::8:800:200C:417A/96 -all"
表示只允许1080::8:800:0000:0000~1080::8:800:FFFF:FFFF范围内的IP地址
"v=spf1 ip6:1080::8:800:68.0.3.1/96 -all"
表示只允许1080::8:800:0000:0000~1080::8:800:FFFF:FFFF范围内的IP地址
4、“a”机制
格式为:
a
a/<prefix-length>
a:<domain>
a:<domain>/<prefix-length>
所有A记录都会检测。如果客户端IP在这些记录中,则该机制结果匹配。
若没有指定域,则使用当前域。
A记录必须与客户端IP地址完全匹配,除非提供前缀长度,在这种情况下,A记录查询返回的IP地址将扩展到其相应的CIDR前缀,且客户端IP将在其子网中查询。
例如:
"v=spf1 a -all"
表示当前域被使用。
"v=spf1 a:example.com -all"
等价于当前域为example.com。
"v=spf1 a:mailers.example.com -all"
表示指定mailers.example.com的主机IP可以外发邮件。
"v=spf1 a/24 a:offsite.example.com/24 -all"
如果example.com解析到192.0.2.1,那么整个C类地址192.0.2.0/24将作为客户端IP地址外发邮件。同样,如果offsite.example.com返回多个A记录,每个IP地址将被扩展到CIDR子网。
5、“mx”机制
格式:
mx
mx/<prefix-length>
mx:<domain>
mx:<domain>/<prefix-length>
所有域的MX记录对应的A记录按照MX优先级进行验证。如果客户端IP在这些记录中,那么该机制匹配。
如果没有指定域,则使用当前域。
A记录必须与客户端IP地址完全匹配,除非提供前缀长度,在这种情况下,A记录查询返回的IP地址将扩展到其相应的CIDR前缀,且客户端IP将在其子网中查询。
例如
"v=spf1 mx mx:deferrals.domain.com -all"
表示允许当前域通过其MX服务器发送邮件,并通过deferrals.domain.com的MX服务器重试延迟的邮件。
"v=spf1 mx/24 mx:offsite.domain.com/24 -all"
也许一个域的MX服务器使用一个IP地址接收邮件,使用另一个相邻IP地址发送邮件。
6、“ptr”机制
格式:
ptr
ptr:<domain>
通过PTP查询客户端IP对应的主机名。对主机名进行验证:PTR主机名对应的A记录至少有一个与原客户端IP匹配,无效主机名将被丢弃。如果一个有效主机名以该域结尾,则该机制匹配。
若没有指定域,则使用当前域。
尽量避免使用该机制,因为会带来很大开销的DNS查询。
例如:
"v=spf1 ptr -all"
直接控制所有机器的域(不像拨号或宽带ISP)允许其所有服务器发送邮件。比如,hotmail.com或者paypal.com。
"v=spf1 ptr:otherdomain.com -all"
表示允许所有以otherdomain.com结尾的主机名的服务器发送邮件。
7、“exists”机制
格式为:
exists:<domain>
对提供的域进行A记录查询。如果有返回结果,则为匹配,无论查询结果是什么。
例如:在下面例子中,客户端IP为1.2.3.4 a,当前域为example.com。
"v=spf1 exists:example.com -all"
若example.com不能解析,则结果返回失败;若能解析,则该机制匹配。
当使用该机制的宏,可以执行RBL方式反向IP查询或者设置每个用户异常。
"exists:%{i}._spf.sparkpostmail.com"用于SPF验证,%{i}为连接的ip地址,通过查询"%{i}._spf.sparkpostmail.com"的A记录,若有返回结果,则允许该ip以MAIL FROM域的名义发送邮件。
以下为两个在审议中的特别的IP地址:
$ host 35.167.215.19._spf.sparkpostmail.com
35.167.215.19._spf.sparkpostmail.com has address 35.167.215.19
$ host 35.167.179.82._spf.sparkpostmail.com
35.167.179.82._spf.sparkpostmail.com has address 35.167.179.82
两者均需通过exists机制。
值得注意的是,SPF记录也包括ptr机制,虽然在最近的SPF RFC版本中已正式弃用,且推荐不使用,但是在执行SPF验证时必须支持。我们发布ptr机制是因为今天美国的邮箱提供商也不能完全解析exists机制。同样,指定的两个IP地址也需通过ptr机制:
$ host 35.167.215.19
19.215.167.35.in-addr.arpa domain name pointer mta523b.sparkpostmail.com.
$ host 35.167.179.82
82.179.167.35.in-addr.arpa domain name pointer mta522b.sparkpostmail.com.
8、“include”机制
格式为:
include:<domain>
表示指定域查询匹配。若查询返回不匹配或者有错误,接着处理下一个机制。警告:如果指定域没有一个有效的SPF记录,结果将返回永久性错误。某些邮件接收者会根据“PermError”拒绝接收邮件。
例如:在下面例子中,客户端IP为1.2.3.4,当前域为example.com.
"v=spf1 include:example.com -all"
若example.com没有SPF记录,结果为“PermError”。
假设example.com的SPF记录为“v=spf1 a -all”,查询example.com的A记录,
若与1.2.3.4匹配,返回“Pass”;
若不匹配,处理包含域的“-all”,include整个匹配失败;
从这个例子的外部指令集可见,最终的结果仍为失败。
因为信任关系,“include”机制可能会被认为有越权行为。需要确保“include”机制不会给跨用户伪造的信息SPF验证返回“Pass”。除非对指定的其他域技术机制到位,从而反正跨用户伪造,“include”机制应该提供“Neutral”处理结果而非“Pass”。即在“include:”前添加“?”前缀。例如:
"v=spf1 ?include:example.com -all"
如此看来,“include”机制不宜选择。
(二)修改符Modifiers
Modifiers是可选的。在每个记录中每个修改符只能使用一次。未知修改符unknown-modifier忽略。
“redirect”修改符
格式为:
redirect=<domain>
表示使用指定域的SPF记录替代当前记录。宏扩展的域也将取代当前域。
例如:在下面例子中,客户端IP为 1.2.3.4 ,当前域为example.com。
"v=spf1 redirect=example.com"
若example.com没有SPF记录,则返回错误,结果是未知的。
假设example.com的SPF记录为“v=spf1 a -all”,查询example.com的A记录,
若与1.2.3.4匹配,则结果为“Pass”;
若不匹配,则匹配失败,接着执行“-all”机制。
“exp”修改符
格式为:
exp=<domain>
若SMTP接收者拒绝邮件,可以返回一个解释信息给发信者。SPF记录中可以包含一个解释字符串给发信者。这样,ISP可以通过网页进一步指导不合格的用户如何配置SASL。
对域进行扩展,执行TXT查询,然后通过宏扩展得到TXT查询结果展示给发信者。其他宏可以用来提供一个自定义。
参考文献
1、SPF RFC协议:http://tools.ietf.org/html/rfc7208
2、SPF协议官方网站:http://www.openspf.org/Introduction