to skip SPF tests when the client host belongs to the
forwarding service.
2. Tests against other identities, such as the "HELO" identity,
may be used to override a failed test against the "MAIL FROM"
identity.
3. For larger domains, it may not be possible to have a complete
or accurate list of forwarding services used by the owners of
the domain’s mailboxes. In such cases, whitelists of
generally-recognized forwarding services could be employed.
9.4. Mail Services
Service providers that offer mail services to third-party domains,
such as sending of bulk mail, may want to adjust their setup in light
of the authorization check described in this document. If the "MAIL
FROM" identity used for such E-Mail uses the domain of the service
provider, then the provider needs only to ensure that its sending
host is authorized by its own SPF record, if any.
If the "MAIL FROM" identity does not use the mail service provider’s
domain, then extra care must be taken. The SPF record format has
several options for the third-party domain to authorize the service
provider’s MTAs to send mail on its behalf. For mail service
providers, such as ISPs, that have a wide variety of customers using
the same MTA, steps should be taken to prevent cross-customer forgery
(see Section 10.4).
9.5. MTA Relays
The authorization check generally precludes the use of arbitrary MTA
relays between sender and receiver of an E-Mail message.
Within an organization, MTA relays can be effectively deployed.
However, for purposes of this document, such relays are effectively
transparent. The SPF authorization check is a check between border
MTAs of different domains.
For mail senders, this means that published SPF records must
authorize any MTAs that actually send across the Internet. Usually,
these are just the border MTAs as internal MTAs simply forward mail
to these MTAs for delivery.
Mail receivers will generally want to perform the authorization check
at the border MTAs, specifically including all secondary MXs. This
allows mail that fails to be rejected during the SMTP session rather
than bounced. Internal MTAs then do not perform the authorization
test. To perform the authorization test other than at the border,
the host that first transferred the message to the organization must
be determined, which can be difficult to extract from the message
header. Testing other than at the border is not recommended.
10. Security Considerations
10.1. Processing Limits
As with most aspects of E-Mail, there are a number of ways that
malicious parties could use the protocol as an avenue for a
Denial-of-Service (DoS) attack. The processing limits outlined here
are designed to prevent attacks such as the following:
o A malicious party could create an SPF record with many references
to a victim’s domain and send many E-Mails to different SPF
clients; those SPF clients would then create a DoS attack. In
effect, the SPF clients are being used to amplify the attacker’s
bandwidth by using fewer bytes in the SMTP session than are used
by the DNS queries. Using SPF clients also allows the attacker to
hide the true source of the attack.
o Whereas implementations of check_host() are supposed to limit the
number of DNS lookups, malicious domains could publish records
that exceed these limits in an attempt to waste computation effort
at their targets when they send them mail. Malicious domains
could also design SPF records that cause particular
implementations to use excessive memory or CPU usage, or to
trigger bugs.
o Malicious parties could send a large volume of mail purporting to
come from the intended target to a wide variety of legitimate mail
hosts. These legitimate machines would then present a DNS load on
the target as they fetched the relevant records.
Of these, the case of a third party referenced in the SPF record is
the easiest for a DoS attack to effectively exploit. As a result,
limits that may seem reasonable for an individual mail server can
still allow an unreasonable amount of bandwidth amplification.
Therefore, the processing limits need to be quite low.
SPF implementations MUST limit the number of mechanisms and modifiers
that do DNS lookups to at most 10 per SPF check, including any
lookups caused by the use of the "include" mechanism or the
"redirect" modifier. If this number is exceeded during a check, a
PermError MUST be returned. The "include", "a", "mx", "ptr", and
"exists" mechanisms as well as the "redirect" modifier do count
against this limit. The "all", "ip4", and "ip6" mechanisms do not
require DNS lookups and therefore do not count against this limit.
The "exp" modifier does not count against this limit because the DNS
lookup to fetch the explanation string occurs after the SPF record
has been evaluated.
When evaluating the "mx" and "ptr" mechanisms, or the %{p} macro,
there MUST be a limit of no more than 10 MX or PTR RRs looked up and
checked.
SPF implementations SHOULD limit the total amount of data obtained
from the DNS queries. For example, when DNS over TCP or EDNS0 are
available, there may need to be an explicit limit to how much data
will be accepted to prevent excessive bandwidth usage or memory usage
and DoS attacks.
MTAs or other processors MAY also impose a limit on the maximum
amount of elapsed time to evaluate check_host(). Such a limit SHOULD
allow at least 20 seconds. If such a limit is exceeded, the result
of authorization SHOULD be "TempError".
Domains publishing records SHOULD try to keep the number of "include"
mechanisms and chained "redirect" modifiers to a minimum. Domains
SHOULD also try to minimize the amount of other DNS information
needed to evaluate a record. This can be done by choosing directives
that require less DNS information and placing lower-cost mechanisms
earlier in the SPF record.
For example, consider a domain set up as follows:
example.com. IN MX 10 mx.example.com.
mx.example.com. IN A 192.0.2.1
a.example.com. IN TXT "v=spf1 mx:example.com -all"
b.example.com. IN TXT "v=spf1 a:mx.example.com -all"
c.example.com. IN TXT "v=spf1 ip4:192.0.2.1 -all"
Evaluating check_host() for the domain "a.example.com" requires the
MX records for "example.com", and then the A records for the listed
hosts. Evaluating for "b.example.com" requires only the A records.
Evaluating for "c.example.com" requires none.
However, there may be administrative considerations: using "a" over
"ip4" allows hosts to be renumbered easily. Using "mx" over "a"
allows the set of mail hosts to be changed easily.
10.2. SPF-Authorized E-Mail May Contain Other False Identities
The "MAIL FROM" and "HELO" identity authorizations must not be
construed to provide more assurance than they do. It is entirely
possible for a malicious sender to inject a message using his own
domain in the identities used by SPF, to have that domain’s SPF
record authorize the sending host, and yet the message can easily
list other identities in its header. Unless the user or the MUA
takes care to note that the authorized identity does not match the
other more commonly-presented identities (such as the From: header
field), the user may be lulled into a false sense of security.
10.3. Spoofed DNS and IP Data
There are two aspects of this protocol that malicious parties could
exploit to undermine the validity of the check_host() function:
o The evaluation of check_host() relies heavily on DNS. A malicious
attacker could attack the DNS infrastructure and cause
check_host() to see spoofed DNS data, and then return incorrect
results. This could include returning "Pass" for an <ip> value
where the actual domain’s record would evaluate to "Fail". See
[RFC3833] for a description of DNS weaknesses.
o The client IP address, <ip>, is assumed to be correct. A
malicious attacker could spoof TCP sequence numbers to make mail
appear to come from a permitted host for a domain that the
attacker is impersonating.
10.4. Cross-User Forgery
By definition, SPF policies just map domain names to sets of
authorized MTAs, not whole E-Mail addresses to sets of authorized
users. Although the "l" macro (Section 8) provides a limited way to
define individual sets of authorized MTAs for specific E-Mail
addresses, it is generally impossible to verify, through SPF, the use
of specific E-Mail addresses by individual users of the same MTA.
It is up to mail services and their MTAs to directly prevent
cross-user forgery: based on SMTP AUTH ([RFC2554]), users should be
restricted to using only those E-Mail addresses that are actually
under their control (see [RFC4409], Section 6.1). Another means to
verify the identity of individual users is message cryptography such
as PGP ([RFC2440]) or S/MIME ([RFC3851]).
10.5. Untrusted Information Sources
SPF uses information supplied by third parties, such as the "HELO"
domain name, the "MAIL FROM" address, and SPF records. This
information is then passed to the receiver in the Received-SPF: trace
fields and possibly returned to the client MTA in the form of an SMTP
rejection message. This information must be checked for invalid
characters and excessively long lines.
When the authorization check fails, an explanation string may be
included in the reject response. Both the sender and the rejecting
receiver need to be aware that the explanation was determined by the
publisher of the SPF record checked and, in general, not the
receiver. The explanation may contain malicious URLs, or it may be
offensive or misleading.
This is probably less of a concern than it may initially seem since
such messages are returned to the sender, and the explanation strings
come from the sender policy published by the domain in the identity
claimed by that very sender. As long as the DSN is not redirected to
someone other than the actual sender, the only people who see
malicious explanation strings are people whose messages claim to be
from domains that publish such strings in their SPF records. In
practice, DSNs can be misdirected, such as when an MTA accepts an
E-Mail and then later generates a DSN to a forged address, or when an
E-Mail forwarder does not direct the DSN back to the original sender.
10.6. Privacy Exposure
Checking SPF records causes DNS queries to be sent to the domain
owner. These DNS queries, especially if they are caused by the
"exists" mechanism, can contain information about who is sending
E-Mail and likely to which MTA the E-Mail is being sent. This can
introduce some privacy concerns, which may be more or less of an
issue depending on local laws and the relationship between the domain
owner and the person sending the E-Mail.
11. Contributors and Acknowledgements
This document is largely based on the work of Meng Weng Wong and Mark
Lentczner. Although, as this section acknowledges, many people have
contributed to this document, a very large portion of the writing and
editing are due to Meng and Mark.
This design owes a debt of parentage to [RMX] by Hadmut Danisch and
to [DMP] by Gordon Fecyk. The idea of using a DNS record to check
the legitimacy of an E-Mail address traces its ancestry further back
through messages on the namedroppers mailing list by Paul Vixie
[Vixie] (based on suggestion by Jim Miller) and by David Green
[Green].
Philip Gladstone contributed the concept of macros to the
specification, multiplying the expressiveness of the language and
making per-user and per-IP lookups possible.
The authors would also like to thank the literally hundreds of
individuals who have participated in the development of this design.
They are far too numerous to name, but they include the following:
The folks on the spf-discuss mailing list.
The folks on the SPAM-L mailing list.
The folks on the IRTF ASRG mailing list.
The folks on the IETF MARID mailing list.
The folks on #perl.
12. IANA Considerations
12.1. The SPF DNS Record Type
The IANA has assigned a new Resource Record Type and Qtype from the
DNS Parameters Registry for the SPF RR type with code 99.
12.2. The Received-SPF Mail Header Field
Per [RFC3864], the "Received-SPF:" header field is added to the IANA
Permanent Message Header Field Registry. The following is the
registration template:
Header field name: Received-SPF
Applicable protocol: mail ([RFC2822])
Status: Experimental
Author/Change controller: IETF
Specification document(s): RFC 4408
Related information:
Requesting SPF Council review of any proposed changes and
additions to this field are recommended. For information about
the SPF Council see http://www.openspf.org/Council
13. References
13.1. Normative References
[RFC1035] Mockapetris, P., "Domain names - implementation and
specification", STD 13, RFC 1035, November 1987.
[RFC1123] Braden, R., "Requirements for Internet Hosts - Application
and Support", STD 3, RFC 1123, October 1989.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2821] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
April 2001.
[RFC2822] Resnick, P., "Internet Message Format", RFC 2822, April
2001.
[RFC3464] Moore, K. and G. Vaudreuil, "An Extensible Message Format
for Delivery Status Notifications", RFC 3464, January
2003.
[RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6
(IPv6) Addressing Architecture", RFC 3513, April 2003.
[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration
Procedures for Message Header Fields", BCP 90, RFC 3864,
September 2004.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66, RFC
3986, January 2005.
[RFC4234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", RFC 4234, October 2005.
[US-ASCII] American National Standards Institute (formerly United
States of America Standards Institute), "USA Code for
Information Interchange, X3.4", 1968.
ANSI X3.4-1968 has been replaced by newer versions with slight
modifications, but the 1968 version remains definitive for
the Internet.
13.2 Informative References
[RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
STD 13, RFC 1034, November 1987.
[RFC1983] Malkin, G., "Internet Users’ Glossary", RFC 1983, August
1996.
[RFC2440] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer,
"OpenPGP Message Format", RFC 2440, November 1998.
[RFC2554] Myers, J., "SMTP Service Extension for Authentication",
RFC 2554, March 1999.
[RFC3696] Klensin, J., "Application Techniques for Checking and
Transformation of Names", RFC 3696, February 2004.
[RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain
Name System (DNS)", RFC 3833, August 2004.
[RFC3851] Ramsdell, B., "Secure/Multipurpose Internet Mail
Extensions (S/MIME) Version 3.1 Message Specification",
RFC 3851, July 2004.
[RFC4409] Gellens, R. and J. Klensin, "Message Submission for Mail",
RFC 4409, April 2006.
[RMX] Danish, H., "The RMX DNS RR Type for light weight sender
authentication", Work In Progress
[DMP] Fecyk, G., "Designated Mailers Protocol", Work In Progress
[Vixie] Vixie, P., "Repudiating MAIL FROM", 2002.
[Green] Green, D., "Domain-Authorized SMTP Mail", 2002.
Appendix A. Collected ABNF
This section is normative and any discrepancies with the ABNF
fragments in the preceding text are to be resolved in favor of this
grammar.
See [RFC4234] for ABNF notation. Please note that as per this ABNF
definition, literal text strings (those in quotes) are case-
insensitive. Hence, "mx" matches "mx", "MX", "mX", and "Mx".
record = version terms *SP
version = "v=spf1"
terms = *( 1*SP ( directive / modifier ) )
directive = [ qualifier ] mechanism
qualifier = "+" / "-" / "?" / "~"
mechanism = ( all / include
/ A / MX / PTR / IP4 / IP6 / exists )
all = "all"
include = "include" ":" domain-spec
A = "a" [ ":" domain-spec ] [ dual-cidr-length ]
MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ]
PTR = "ptr" [ ":" domain-spec ]
IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ]
IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ]
exists = "exists" ":" domain-spec
modifier = redirect / explanation / unknown-modifier
redirect = "redirect" "=" domain-spec
explanation = "exp" "=" domain-spec
unknown-modifier = name "=" macro-string
ip4-cidr-length = "/" 1*DIGIT
ip6-cidr-length = "/" 1*DIGIT
dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
ip4-network = qnum "." qnum "." qnum "." qnum
qnum = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
/ "25" %x30-35 ; 250-255
; conventional dotted quad notation. e.g., 192.0.2.0
ip6-network = <as per [RFC 3513], section 2.2>
; e.g., 2001:DB8::CD30
domain-spec = macro-string domain-end
domain-end = ( "." toplabel [ "." ] ) / macro-expand
toplabel = ( *alphanum ALPHA *alphanum ) /
( 1*alphanum "-" *( alphanum / "-" ) alphanum )
; LDH rule plus additional TLD restrictions
; (see [RFC3696], Section 2)
alphanum = ALPHA / DIGIT
explain-string = *( macro-string / SP )
macro-string = *( macro-expand / macro-literal )
macro-expand = ( "%{" macro-letter transformers *delimiter "}" )
/ "%%" / "%_" / "%-"
macro-literal = %x21-24 / %x26-7E
; visible characters except "%"
macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" /
"c" / "r" / "t"
transformers = *DIGIT [ "r" ]
delimiter = "." / "-" / "+" / "," / "/" / "_" / "="
name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
header-field = "Received-SPF:" [CFWS] result FWS [comment FWS]
[ key-value-list ] CRLF
result = "Pass" / "Fail" / "SoftFail" / "Neutral" /
"None" / "TempError" / "PermError"
key-value-list = key-value-pair *( ";" [CFWS] key-value-pair )
[";"]
key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string )
key = "client-ip" / "envelope-from" / "helo" /
"problem" / "receiver" / "identity" /
mechanism / "x-" name / name
identity = "mailfrom" ; for the "MAIL FROM" identity
/ "helo" ; for the "HELO" identity
/ name ; other identities
dot-atom = <unquoted word as per [RFC2822]>
quoted-string = <quoted string as per [RFC2822]>
comment = <comment string as per [RFC2822]>
CFWS = <comment or folding white space as per [RFC2822]>
FWS = <folding white space as per [RFC2822]>
CRLF = <standard end-of-line token as per [RFC2822]>
Appendix B. Extended Examples
These examples are based on the following DNS setup:
; A domain with two mail servers, two hosts
; and two servers at the domain name
$ORIGIN example.com.
@ MX 10 mail-a
MX 20 mail-b
A 192.0.2.10
A 192.0.2.11
amy A 192.0.2.65
bob A 192.0.2.66
mail-a A 192.0.2.129
mail-b A 192.0.2.130
www CNAME example.com.
; A related domain
$ORIGIN example.org.
@ MX 10 mail-c
mail-c A 192.0.2.140
; The reverse IP for those addresses
$ORIGIN 2.0.192.in-addr.arpa.
10 PTR example.com.
11 PTR example.com.
65 PTR amy.example.com.
66 PTR bob.example.com.
129 PTR mail-a.example.com.
130 PTR mail-b.example.com.
140 PTR mail-c.example.org.
; A rogue reverse IP domain that claims to be
; something it’s not
$ORIGIN 0.0.10.in-addr.arpa.
4 PTR bob.example.com.
B.1. Simple Examples
These examples show various possible published records for
example.com and which values if <ip> would cause check_host() to
return "Pass". Note that <domain> is "example.com".
v=spf1 +all
-- any <ip> passes
v=spf1 a -all
-- hosts 192.0.2.10 and 192.0.2.11 pass
v=spf1 a:example.org -all
-- no sending hosts pass since example.org has no A records
v=spf1 mx -all
-- sending hosts 192.0.2.129 and 192.0.2.130 pass