Common SPF Errors & Fixes

Version 1

    Syntax Recommendations

    Common Look Up mechanisms

    a:

    mx:

    include:

    ip4:

    ip6:

    exists:

    ptr:

    all

    Common Modifiers

    redirect=

    exp=

     

    1. An A Record must ALWAYS contain IP address (map host to IP)
    2. CNAME (Alias) must contain hostnames. No IPs here
    3. NS an MX records must contain host names. No IPs allowed.
    4. MX records (for mail servers)  should contain hostnames NOT IPs.

    Too Many Mechanisms

    Section 10.1, "Processing Limits" of the SPF RFC 4408 specifies the following in regards to DNS lookups:

    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.

    This limit is in place to prevent SPF lookups from being a useful avenue for Denial of Service attacks.

    Using an example SPF record as an example to illustrate, this record was breaking with 12 look-ups:

    example.com text = "v=spf1 include:_spf-a.example.com include:_spf-b.example.com include:_spf-c.example.com include:_spf-ssg-a.example.com include:spf-a.anotherexample.com ip4:131.107.115.215 ip4:131.107.115.214 ip4:205.248.106.64 ip4:205.248.106.30 ip4:205.248.106.32 ~all" [ 5 mechanisms]

    _spf-a.example.com  text = "v=spf1 ip4:216.99.5.67 ip4:216.99.5.68 ip4:202.177.148.100 ip4:203.122.32.250 ip4:202.177.148.110 ip4:213.199.128.139 ip4:213.199.128.145 ip4:207.46.50.72 ip4:207.46.50.82 a:mh.example.m0.net ~all"  [ +1 = 6 mechanisms]

    mh.example.m0.net a = 209.11.164.116

    _spf-b.example.com text = "v=spf1 include:spf.messaging.example.com ip4:207.46.22.35 ip4:207.46.22.98 ip4:207.46.22.101 ip4:131.107.1.27 ip4:131.107.1.17 ip4:131.107.65.22 ip4:131.107.65.131 ip4:131.107.1.101 ip4:131.107.1.102 ip4:217.77.141.52 ip4:217.77.141.59 ~all" [+1 = 7 mechanisms]

    spf.messaging.example.com text = "v=spf1 include:spfa.anotherexample.com include:spfb.anotherexaple.com include:spfc.anotherexample.com -all"  [+3 = 10 mechanisms]

    spfa.anotherexample.com  text = "v=spf1 ip4:157.55.116.128/26 ip4:157.55.133.0/24 ip4:157.55.158.0/23 ip4:157.55.234.0/24 ip4:157.56.112.0/24 ip4:157.56.116.0/25 ip4:157.56.120.0/25 ip4:207.46.100.0/24 ip4:207.46.108.0/25 ip4:207.46.163.0/24 ip4:134.170.140.0/24 ip4:157.56.110.0/23 -all" [+0 = 10 mechanisms]

    spfb.anotherexample.com  text = "v=spf1 ip4:207.46.51.64/26 ip4:213.199.154.0/24 ip4:213.199.180.128/26 ip4:216.32.180.0/23 ip4:64.4.22.64/26 ip4:65.55.83.128/27 ip4:65.55.169.0/24 ip4:65.55.88.0/24 ip4:94.245.120.64/26 ip4:131.107.0.0/16 ip4:157.56.73.0/24 ip4:134.170.132.0/24 -all" [+0 = 10 mechanisms]

    spfc.anotherexample.com  text = "v=spf1 ip4:207.46.101.128/26 ip6:2a01:111:f400:7c00::/54 ip6:2a01:111:f400:fc00::/54 ip4:157.56.87.192/26 ip4:157.55.40.32/27 ip4:157.56.123.0/27 ip4:157.56.91.0/27 ip4:157.55.206.0/24 ip4:157.55.207.0/24 ip4:157.56.206.0/23 ip4:157.56.208.0/22 -all" [ +0 = 10 mechanisms]

    _spf-c.example.com  text = "v=spf1 ip4:203.32.4.25 ip4:213.199.138.181 ip4:213.199.138.191 ip4:207.46.52.71 ip4:207.46.52.79 ip4:131.107.1.18 ip4:131.107.1.19 ip4:131.107.1.20 ip4:131.107.1.48 ip4:131.107.1.56 ip4:86.61.88.25 ip4:131.107.1.44 ip4:131.107.1.37 ~all" [+0 = 10 mechanisms]

    _spf-ssg-a.example.com  text = "v=spf1 include:_spf-ssg-b.example.com include:_spf-ssg-c.example.com ~all"  [+2 = 12 mechanisms]

    _spf-ssg-b.example.com  text = "v=spf1 ip4:207.68.169.173/30 ip4:207.68.176.1/26 ip4:207.46.132.129/27 ip4:207.68.176.97/27 ip4:65.55.238.129/26 ip4:207.46.222.193/26 ip4:207.46.116.135/29 ip4:65.55.178.129/27 ip4:213.199.161.129/27 ip4:65.55.33.70/28 ~all"  [+0 = 12 mechanisms]

    _spf-ssg-c.example.com text = "v=spf1 ip4:65.54.121.123/29 ip4:65.55.81.53/28 ip4:65.55.234.192/26 ip4:207.46.200.0/27 ip4:65.55.52.224/27 ip4:94.245.112.10/31 ip4:94.245.112.0/27 ip4:111.221.26.0/27 ip4:207.46.50.221/26 ip4:207.46.50.224 ~all" [+0 = 12 mechanisms]

    spf-a.secondexample.com  text = "v=spf1 ip4:157.55.0.192/26 ip4:157.55.1.128/26 ip4:157.55.2.0/25 ip4:65.54.190.0/24 ip4:65.54.51.64/26 ip4:65.54.61.64/26 ip4:65.55.111.0/24 ip4:65.55.116.0/25 ip4:65.55.34.0/24 ip4:65.55.90.0/24 ip4:65.54.241.0/24 ip4:207.46.117.0/24 ~all" [+0 = 12 mechanisms]

    Character String Too Long

    255 character limitation in a single string

    https://kb.isc.org/article/AA-00356/0/Can-I-have-a-TXT-or-SPF-record-longer-than-255-characters.html

    http://www.string-functions.com/length.aspx

    You may have more than 255 characters of data in a TXT or SPF record, but not more than 255 characters in a single string.
    If you attempt to create an SPF or TXT record with a long string (>255 characters) in it, BIND will give an error 
    (e.g. "invalid rdata format: ran out of space".)  Strings in SPF and TXT records should be no longer than 255 characters. 
    However to get around this limitation, per RFC 4408 a TXT or SPF record is allowed to contain multiple strings, which
    should be concatenated together by the reading application.  In the case of use for SPF (using either TXT or SPF RRs)
    the strings are concatenated together without spaces as described below.  Reassembly by other applications of multiple
    strings stored in TXT records might work differently.


    3.1.3. Multiple Strings in a Single DNS record


    As defined in [RFC1035] sections 3.3.14 and 3.3, a single text DNS
    record (either TXT or SPF RR types) can be composed of more than one
    string. If a published record contains multiple strings, then the
    record MUST be treated as if those strings are concatenated together
    without adding spaces. For example:

    IN TXT "v=spf1 .... first" "second string..."

    MUST be treated as equivalent to

    IN TXT "v=spf1 .... firstsecond string..."

    SPF or TXT records containing multiple strings are useful in
    constructing records that would exceed the 255-byte maximum length of
    a string within a single TXT or SPF RR record.

    EXAMPLE

    text = "v=spf1 ip4:199.15.212.0/22 ip4:72.3.185.0/24 ip4:72.32.154.0/24 ip4:72.32.217.0/24 ip4:72.32.243.0/24 ip4:94.236.119.0/26  ip4:37.188.97.188/32 ip4:185.28.196.0/22 ~all“

    text = "v=spf1 ip4:199.15.212.0/22 " ip4:72.3.185.0/24 ip4:72.32.154.0/24 ip4:72.32.217.0/24" " ip4:72.32.243.0/24 ip4:94.236.119.0/26" " ip4:37.188.97.188/32 ip4:185.28.196.0/22 ~all"

    Null Records in the SPF Record

    A record that is NULL or that does not exist will break an SPF record.  Syntax within the record is very important, if there are extra spaces between mechanisms it will count as NULL.

    EXAMPLE

    text = "v=spf1 ip4:199.15.212.0/22“ <- accurate

    text = "v=spf1 ip4: 199.15.212.0/22<- NULL (NOTE the space between IP4: and the IP)

    Repetitive Records in the SPF Record - Void Lookups

    If there are too many repetitive mechanisms in the SPF record, including records that cascade (for example when using "include:") the record will break.

    There is a MAX of 2 void look ups in an SPF record.  More than that and the record will break.  This prevents SPF records from being used in Denial of Service style attacks.

    Validation Tools

    SPF checker, syntax validator and SPF tester

    http://www.kitterman.com/spf/validate.html

    SPF checker

    http://vamsoft.com/support/tools/spf-policy-tester

    SPF validator

    http://vamsoft.com/support/tools/spf-syntax-validator

    CIDR Calculator

    http://www.subnet-calculator.com/cidr.php

    Nslookup

    http://network-tools.com/nslook/

    SPF creation wizard

    http://www.microsoft.com/mscorp/safety/content/technologies/senderid/wizard/

    Common SPF errors

    http://www.openspf.org/FAQ/Common_mistakes

    SPF syntax definitions

    http://www.openspf.org/SPF_Record_Syntax