Patrick Ben Koetter <p@sys4.de>
2022-08-30
Abbreviation for Sender Policy Framework
IETF Standard RFC 7208
A DNS-based mechanism to identify (un)authorized hosts sending on behalf of a domain
A sender-side email policy mechanism
A senderdomain uses DNS to publish it’s email sending policy
The policy lists legitimate DNS records and / or IP-addresses / -ranges that may send email on behalf or the senderdomain
All hosts listed, except for the last ones quantified with
all, may send on behalf of the senderdomain
A receiver checks if the client IP-address is on the list of legitimate hosts
example.com
example.com. 86400 IN TXT "v=spf1 -all"
sys4.de
sys4.de. 3600 IN TXT "v=spf1 ip4:194.126.158.132 ip4:194.126.158.144 ip6:2001:1578:400:111::7 -all"
switch.ch
switch.ch. 900 IN TXT "v=spf1 mx:cloud.switch.ch exists:%{ir}.spf.switch.ch include:mail.zendesk.com include:spf.protection.outlook.com -all"
SPF has always been considered to be br0ken by design
The mechanism assumes a static environment, but IT isn’t
It breaks forwarding e.g. on mailing lists
IP has become an unreliable reputation indicator i.e. on shared platforms
Identify all legitimate hosts
Prefer IP-notation over DNS records if possible
Create TXT record in APEX of (sub)domain
Monitor success / failure reports
"<version> <legitimate hosts> <treatment><all others>"
A SPF record is a DNS TXT resource record
Statements in the record a will be evaluated left to right
Version
Mechanisms
Modifier
Qualifier
A valid SPF record MUST contain a version statement
The version statement MUST be the first entry in the TXT record
The only valid version statement today is
v=spf1
| Mechanism | Validity |
|---|---|
|
Matches any host (catchall) |
|
Matches a DNS A record |
|
Matches a DNS MX record |
| Mechanism | Validity |
|---|---|
|
Matches an IPv4 address (range) |
|
Matches an IPv6 address (range) |
|
Refers to another DNS entry whose record is part of this domains policy |
| Modifier | Description |
|---|---|
|
Use another domains SPF policy |
|
Refer to TXT record for explanation if client is rejected |
| Qualifier | Result | Description |
|---|---|---|
+ |
|
Authorize (Allow) host to send |
- |
|
Host is not authorized. Reject transport. |
~ |
|
Host is not authorized. Treat error generously |
? |
|
Host is neither authorized nor
unauthorized. Treat like |
IP vs. DNS RR
IP-address vs. IP-range
Keep vs. handover control
Filtering costs time and ressources
Design SPF for speed
How many DNS lookups to resolve a MX?
How many DNS lookups to resolve an IP?
SPF serves to filter unauthorized mail clients
The smaller the network the bigger the trust
What’s the risk assessment for sys4.de?
What’s the risk assessment for bund.de?
What’s the risk assessment for switch.ch?
What’s the risk assessment for
swisssign.ch?
What’s the risk assessment for swisscom.ch?
Production (swisssign.ch)
"v=spf1 include:spf.protection.outlook.com a:mx1.swisssign.com a:mx2.swisssign.com a:mx3.swisssign.com a:mx4.swisssign.com mx:swisssign.com -all"
Increase lookup performance, remove loop
"v=spf1 include:spf.protection.outlook.com a:91.194.146.13 a:91.194.146.14 a:91.194.146.15 a:91.194.146.16 -all"
Simplify and speed up
"v=spf1 include:spf.protection.outlook.com a:91.194.146.0/27 -all"
Reduce risk
"v=spf1 include:spf.protection.outlook.com a:91.194.146.8/29 -all"
Two delegation modifiers – include and
redirect.
include & redirect
"v=spf1 include:_spf.example.com ~all"
"v=spf1 redirect:_spf.example.com"
_spf.example.com
"v=spf1 ip4:192.2.0.1 ip4:192.2.0.1 -all"
includeinclude allows to (locally) control the all
modifier.
Use it for organizations with many subdomains and / or when introducing SPF
redirectredirect gives it all to the (remote) SPF policy
Use it for parked / null MX (sub)domains and / or when identical policy level has been reached and has become stable