Next: Appendix 3 Up: Network Liaison's Handbook Previous: Appendix: IP Address Registry (IPR)
Appendix: Sender Policy Framework (SPF)
Sender Policy Framework (SPF) is a DNS-based mechanism for describing which hosts are allowed to send mail for a domain, in the form of a TXT record. It is defined by RFC 7208, and is recommended to be configured for any departmental mail servers.
We currently have no automated process with which to add TXT records to the VT DNS servers. Instead, NLs must email the hostmaster to request a manual record entry.
A full explanation of how SPF works, why you should use it, or how you should construct your own policy are beyond the scope of this document, but we provide the following to make it easier to write a basic policy.
Recommended Records
Self-hosted (on VT campus)
For any self-run mail server, we strongly recommend configuring an SPF merely allowing the mail exchanger and soft-failing all other domains:
v=spf1 +mx ~all
Please note: it is important that your mail exchanger has reverse records for any addresses it uses to send; many domains filter based on reverse DNS. If you have users sending mail from several IP addresses, please refer to the more extensive documentation below or in the RFC to construct your records.
Third-party
If you outsource your departmental mail server to outlook.com
Exchange, or
some other service, they should provide guidance on the SPF record you should
use. For Exchange, that will likely look like:
v=spf1 include:spf.protection.outlook.com ~all
Summary of SPF record format
Section 5 of RFC 7208 is currently the authoritative source for the definition of SPF records, however we attempt to summarize common options with examples here, for convenience.
Statement composition
Every SPF record is stored in a TXT record. e.g.:
$ dig +short txt wuvt.vt.edu
"v=spf1 ip4:128.173.235.0/27 ip6:2001:468:c80:a102:1:1000:1024:0/120 ip6:2607:b400:000a:0280::/64 mx a include:_spf.google.com ~all"
Historically, they were stored in the SPF record type, however this is considered deprecated, and should not be used.
A record consists of 2 parts: a version declaration, and a set of declarations
(called "mechanisms" in the RFC) defining allowed senders. Every declaration is
prefixed with one of + - ~ ?
, which are defined to mean "pass", "fail",
"softfail", and "none", respectively (with an implied pass, if no modifier is
prefixed).
"all" and "include" are special declarations; "include" references the SPF for another domain, and "all" matches any other hosts (and must be the last declaration).
We provide examples and explanation of the most common mechanisms for convenience. Full EBNF syntax is provided in the RFC.
"a"
This declaration performs a DNS lookup to see if address records match the sender. e.g.:
v=spf1 a:mail.cns.vt.edu ~all
In this example, if the A or AAAA record for mail.cns.vt.edu resolves to the
sending address, this will pass, and all others will soft fail. If "a" is
provided without a domain, it is assumed to be the same as that for the record.
Thus, v=spf1 a ~all
in a record for cns.vt.edu
would be equivalent to
v=spf1 a:cns.vt.edu ~all
Further, this declaration type can be used with CIDR prefixes. Consider:
$ dig +short a wuvt.vt.edu && dig +short aaaa wuvt.vt.edu
128.173.235.21
2001:468:c80:a102:1:1000:1024:3
The above spf for wuvt.vt.edu could be reduced to:
v=spf1 a:wuvt.vt.edu/27/120 ip6:2607:b400:000a:0280::/64 mx include:_spf.google.com ~all
Notice this uses "dual cidr" notation specified in the RFC. This is tricky behavior, and we do not recommend it.
"mx"
This declaration behaves similarly to the "a" declaration above, however it triggers lookups for the specified MX record, instead.
"ip4" and "ip6"
These declarations test whether the source IP is in a given IP network. In the
WUVT example from above, it allows ip4:128.173.235.0/27
,
ip6:2001:468:c80:a102:1:1000:1024:0/120
, and ip6:2607:b400:000a:0280::/64
with CIDR prefixes behaving as expected.
"include"
The include mechanism is designed to allow the SPF records from other domains to be evaluated as an ancilliary statement, for example when someone else provides your mail services.
Please note the following from the RFC:
In hindsight, the name "include" was poorly chosen. Only the evaluated result of the referenced SPF record is used, rather than literally including the mechanisms of the referenced record in the first. For example, evaluating a "-all" directive in the referenced record does not terminate the overall processing and does not necessarily result in an overall "fail". (Better names for this mechanism would have been "if-match", "on-match", etc.)
"all"
As previously noted, the "all" declaration matches any other source addresses,
and must be last. The astute reader will note that we always specify ~all
instead of -all
. This is because it is fairly difficult to accurately predict
what source IPs will be used for sending mail in certain configurations, and
implementations vary on how strictly they enforce a hard fail. Thus, a softfail
is less likely to cause issues.
Next: Appendix 3 Up: Network Liaison's Handbook Previous: Appendix: IP Address Registry (IPR) Eric C. Landgraf 2019-05-07