This is essentially going to be a summary of the information that appears on the OpenSPF documentation web page. Really, what else can I say that isn’t said there? But, if you’re like me and rarely bother clicking on links inside of blog posts and would prefer to read it within the same web page you navigated to, then read on. For brevity’s sake I will split this into a couple of posts. In my previous posts, I’ve stated that SPF is a method of authentication where the receiving email host checks to see if the transmitting IP is allowed to send mail for the domain in the envelope sender. It’s actually a bit more complicated than that. In an SPF record, a domain defines zero or more mechanisms. Mechanisms can be used to describe the set of hosts which are designated outbound mailers for the domain in the envelope sender. all | ip4 | ip6 | a | mx | ptr | exists | include Domains may also define modifiers. Each modifier can appear only once. redirect | exp
Mechanisms Mechanisms can be prefixed with one of four qualifiers:

“+” Pass
“-” Hard Fail
“~” Soft Fail
“?” Neutral

If a mechanism results in a hit, its qualifier value is used. The default qualifier is “+“, i.e. “Pass”. If no mechanism or modifier matches, the default result is “Neutral”. Mechanisms are evaluated in order. If a domain has no SPF record at all, the result is “None”. If a domain has a temporary error during DNS processing, the result is “TempError” (called “Error” in earlier posts and earlier drafts of SPF). If some kind of syntax or evaluation error occurs (eg. the domain specifies an unrecognized mechanism) the result is “PermError” (formerly “Unknown”).
Sample SPF records Below are some examples of sample SPF records that a domain could publish using the syntax above. The first part, v=spf1, means that the version of SPF that the domain has set up for that record is SPF version 1.0. We will revisit how to interpret the rest of the line in subsequent posts.

"v=spf1 -all" "v=spf1 a -all" "v=spf1 a mx -all" "v=spf1 +a +mx -all"


Evaluation
Evaluation of the SPF record can return any of these results: Result: Pass
Explanation: The SPF record designates the host to be allowed to send.
Intended action: Accept This is the type of action I like to see. This is useful when combined with safe senders as it means that the envelope sender that claims to have sent the mail really did send the mail. Result: Hard Fail
Explanation: The SPF record has designated the host as NOT being allowed to send.
Intended action: Reject In Exchange Hosted Services, we have custom delivery options for Hard Fails. If the customer chooses, we will auto-quarantine SPF Hard Fails. If they don’t opt-in, we add spam points more aggressively but do not automatically send it to spam quarantine. Result: Soft Fail
Explanation: The SPF record has designated the host as NOT being allowed to send but is in transition.
Intended action: Accept but mark In Exchange Hosted Services, we add spam points but not as aggressively as a Hard Fail. Result: None
Explanation: The domain does not have an SPF record or the SPF record does not evaluate to a result.
Intended action: Accept My own opinion on SPF None differs from OpenSPF. Rather than having the intended action as accept, I would treat it as “proceed, but we’re keeping an eye on you.” I say this because domains without SPF records are more easily exploited (spoofed). Result: Neutral
Explanation: The SPF record specifies explicitly that nothing can be said about validity.
Intended action: Accept My opinion on an SPF Neutral is similar to SPF None, but I would not be as suspicious. At least with SPF Neutral, the owner of the domain took the time to set up SPF records and explicitly stated “We neither confirm nor deny.” Result: PermError (Unknown)
Explanation: A permanent error has occured (eg. badly formatted SPF record).
Intended action: Unspecified My own opinion on this is the following: Come on, avoid syntax errors in your SPF records. Sheesh… On the other hand, maybe you’re a spammer and you’re doing it on purpose. Result: TempError (Error)
Explanation: A transient error has occured.
Intended action: Accept or Reject I’m not sure an reject is justified on this action. Errors can occur because of network hiccups so I wouldn’t reject it because of that. One thing I’d like to point out is that OpenSPF uses the term “Fail” where I say “Hard Fail.” We call it Hard Fail in our filters and I’ve gotten used to saying it that way. However, if I ever say SPF Fail, I mean an SPF Hard Fail and never a Soft Fail.
Read More… (From Terry Zink’s Anti-spam Blog)

Moving onwards to mechanisms, let’s take a look at them in a bit more detail. Again, this information comes straight from the OpenSPF page, with extra commentary by me. The all mechanism all This mechanism always matches. It usually goes at the end of the SPF record.

Example 1 v=spf1 mx -all Allow the domain’s MXes to send mail for the domain, prohibit all others. Reading the syntax from left to right, the version of SPF is 1.0, return a pass if the sending IP is in the MX records for the domain, return a Fail on everything else. Note that the implied syntax is the following: v=spf1 +mx -all
Example 2
v=spf1 -all The domain sends no mail at all. Read left to right, the version of SPF is 1.0, return a Fail on everything (ie, if any IP has this domain name in the envelope sender, return a Hard Fail).
Example 3
v=spf1 +all A record like this defeats the purpose of SPF. To interpret it, the version of SPF is 1.0, return a pass on everything. If you are returning a pass on everything, it means that whatever IP is sending mail for your domain, you say that’s okay. That means any IP can forge your domain.

The ip4 mechanism
ip4:<ip4-address>ip4:<ip4-network>/<prefix-length>

The argument to the “ip4:” mechanism is an IPv4 network range. If no prefix-length is given, /32 is assumed (singling out an individual host address). This is one of the easier records to interpret.

Example 1"v=spf1 ip4:192.168.0.1/16 -all"Allow any IP address between 192.168.0.1 and 192.168.255.255. If the transmitting IP is not within this range, return a Hard Fail.

The ip6 mechanism
ip6:<ip6-address>ip6:<ip6-network>/<prefix-length>

The argument to the “ip6:” mechanism is an IPv6 network range. If no prefix-length is given, /128 is assumed (singling out an individual host address).

Example 1"v=spf1 ip6:1080::8:800:200C:417A/96 -all"Allow any IPv6 address between 1080::8:800:0000:0000 and 1080::8:800:FFFF:FFFF.
Example 2"v=spf1 ip6:1080::8:800:68.0.3.1/96 -all"Allow any IPv6 address between 1080::8:800:0000:0000 and 1080::8:800:FFFF:FFFF.

The a mechanism
aa/<prefix-length>a:<domain>a:<domain>/<prefix-length>

All the A records for the domain are tested. If the client IP is found among them, this mechanism matches.If domain is not specified, the current-domain is used.The A records have to match the client IP exactly, unless a prefix-length is provided, in which case each IP address returned by the A lookup will be expanded to its corresponding CIDR prefix, and the client IP will be sought within that subnet.

Example 1

v=spf1 a -allLookup the A-record of the current domain. If it matches the transmitting IP, return a Pass. If not, return a Fail.
Example 2v=spf1 a:example.com -allLookup the A-record of example.com. If it matches the transmitting IP, return a Pass. If not, return a Fail.
Example 3v=spf1 a:mailers.example.com -allExample.com has explicitly listed all of its outbound mailers in a special A-record under mailers.example.com. Lookup the A-record for mailers.example.com, and if the transmitting IP is found amoung them, return a Pass. If it is not, return a Fail.
Example 4v=spf1 a/24 a:offsite.example.com/24 -allThis SPF record lists two possible mailers, a/24 and a:offsite.example.com/24. Lookup the A-record of teh current domain and assume that it resolves to 192.0.2.1; the entire class C of 192.0.2.0/24 would be searched for the client IP. Similarly, assume that the A-record for offsite.example.com is 192.0.3.1. It would be expanded to 192.0.3.0/24 and would be searched for transmitting IP. If more than one A record were returned for the domain, each one would be expanded to a CIDR subnet.

If not match was no found, a Fail would be returned.

In my next post, we will get to the mx, ptr, exists and include mechanisms, and then we will get to the modifiers. Finally, we will take a look at some real-life SPF records.
Read More… (From Terry Zink’s Anti-spam Blog)

“The performance is back to what it was prior to having that problem, so we don’t see delays anymore,”Stafford said. “Barracuda’s been very helpful.”

Last week, some customers of BTINet may have experienced delays in receiving e-mails, anywhere from a five-minute hold to up to eight hours. via BismarckTribune
Read More… (From Email Spam News)

“Stanley violated the temporary restraining order by knowingly sending spam e-mails that falsely disparaged…Jaburg & Wilk.”

A company claiming to defend online reputations is found liable for harassment, spam and death threats. via CNET News.com
Read More… (From Email Spam News)

Checked your e-mail lately? If so, you probably had to sift through a nasty pile of spam. via Rediff.com
Read More… (From Email Spam News)

I’ve had a document sitting on my shelf (ie, the window-sill 10 feet away from my desk) for about 6 months now just waiting to be read. It’s entitled Sender Repuration in a Large Webmail Service. It’s by Bradley Taylor, at Google, and is available to be read at the past documents from the Conference in Email and Antispam, 2006. Anyways, I finally got around to reading it this week. Like everyone else, Gmail uses a lot of Sender Authentication to do their filtering. One of the ways they authenticate mail is with SPF, and for domains without SPF they use an algorithm they dub “Best-Guess SPF” which is meant to be a temporary measure until more domains come onboard and start publishing their SPF records. They readily admit that the technique isn’t perfect, but it’s not bad, either. Basically, it works in the following manner: 1. Check the domain of the envelope sender. If it doesn’t publish SPF records, then check the MX-records and A-records of the sender’s domain. If the sending domain comes from the same range of IPs as the MX-record or A-record, then the sender has been authenticated.

Example 1 (using fictitious numbers) Transmitting IP = 4.8.15.16
Envelope sender = me@lost.com
A-record of lost.com = 4.8.15.11
MX-record of lost.com = 4.8.15.0/27 (4.8.15.0 - 4.8.15.31) Since the transmitting IP is within the range of the MX-records (an abnormally large MX record, but hey, this example is fictitious), we have an authentication.

2. If that doesn’t work, get the reverse DNS of the sending IP. If it matches the domain of the envelope sender, then the sender has been authenticated.

Example 2 Transmitting IP = 4.8.15.16
Envelope sender = me@lost.com
Reverse DNS of 4.8.15.16 = lost.com The reverse DNS name matches the name of the domain in the envelope sender, so the sender is authenticated. Example 3 Transmitting IP = 16.23.42.108
Envelope sender = me@others.com
Reverse DNS of 16.23.42.108 = island.com The reverse DNS name does not match the envelope sender, therefore, no sender authentication.

3. If that doesn’t work, use a technique that is referred to as PTR zone. If the sender is a subdomain of the DNS PTR’s zone, then it is authenticated as if the sender comes from the zone itself. The example given in the document where I discovered this seems a bit backwards, so I’m going to clean it up a bit in order to conform to the description given.

Example 4 Transmitting IP = 16.23.42.108
Envelope sender = me@island.others.com
Reverse DNS of 16.23.42.108 = domain in PTR zone = airplane.others.com This is close, but not an authentication. The envelope sender (island.others.com) is not a subdomain of the domain in the PTR zone (airplane.others.com). Example 5 Transmitting IP = 16.23.42.108
Envelope sender = me@island.others.com
Reverse DNS of 16.23.42.108 = domain in PTR zone = others.com The domain of the sender (island.others.com) is a subdomain of others.com, and therefore we have an authentication.

Using this extra bit of authentication allows Gmail to authenticate almost twice as much mail as a standard SPF check. That’s actually pretty good. As to whether or not this is a good idea, OpenSPF has this to say about it:

Best-guess processing is a crude, non-standard attempt at guessing the IP address range of a domain’s outgoing mailservers. “Non-standard” means it is not standardized and specific to the implementation. … Some find this remarkably good at detecting unforged messages from domains that have not yet published SPF records. Others consider it a security hole because it gives attackers a lot of additional potential targets (authorized hosts) to hack in order to abuse the domain.

From an anti-spam perspective, I think sender authentication is a good idea but it all depends on how it is used. In my opinion, successful authentication is best used in conjunction with safe senders. I first voiced my opinion a few weeks ago when I thought it was a security risk. However, at the time I don’t think I was thinking ahead; I think the way to implement a safelist is to allow a sender to be on a safelist (ie, bypass spam filtering) if the sender can be authenticated. That way, spoofing the sender doesn’t work and if they do start spamming, there’s a much more reliable paper trail.
Read More… (From Terry Zink’s Anti-spam Blog)

I’ve had a document sitting on my shelf (ie, the window-sill 10 feet away from my desk) for about 6 months now just waiting to be read. It’s entitled Sender Repuration in a Large Webmail Service. It’s by Bradley Taylor, at Google, and is available to be read at the past documents from the Conference in Email and Antispam, 2006. Anyways, I finally got around to reading it this week. Like everyone else, Gmail uses a lot of Sender Authentication to do their filtering. One of the ways they authenticate mail is with SPF, and for domains without SPF they use an algorithm they dub “Best-Guess SPF” which is meant to be a temporary measure until more domains come onboard and start publishing their SPF records. They readily admit that the technique isn’t perfect, but it’s not bad, either. Basically, it works in the following manner:

1. Check the domain of the envelope sender. If it doesn’t publish SPF records, then check the MX-records and A-records of the sender’s domain. If the sending domain comes from the same range of IPs as the MX-record or A-record, then the sender has been authenticated. Example 1 (using fictitious numbers) Transmitting IP = 4.8.15.16
Envelope sender = me@lost.com
A-record of lost.com = 4.8.15.11
MX-record of lost.com = 4.8.15.0/27 (4.8.15.0 - 4.8.15.31) Since the transmitting IP is within the range of the MX-records (an abnormally large MX record, but hey, this example is fictitious), we have an authentication.
2. If that doesn’t work, get the reverse DNS of the sending IP. If it matches the domain of the envelope sender, then the sender has been authenticated. Example 2 Transmitting IP = 4.8.15.16
Envelope sender = me@lost.com
Reverse DNS of 4.8.15.16 = lost.com The reverse DNS name matches the name of the domain in the envelope sender, so the sender is authenticated. Example 3 Transmitting IP = 16.23.42.108
Envelope sender = me@others.com
Reverse DNS of 16.23.42.108 = island.com The reverse DNS name does not match the envelope sender, therefore, no sender authentication.
3. If that doesn’t work, use a technique that is referred to as PTR zone. If the sender is a subdomain of the DNS PTR’s zone, then it is authenticated as if the sender comes from the zone itself. The example given in the document where I discovered this seems a bit backwards, so I’m going to clean it up a bit in order to conform to the description given.

Example 4 Transmitting IP = 16.23.42.108
Envelope sender = me@island.others.com
Reverse DNS of 16.23.42.108 = domain in PTR zone = airplane.others.com This is close, but not an authentication. The envelope sender (island.others.com) is not a subdomain of the domain in the PTR zone (airplane.others.com). Example 5 Transmitting IP = 16.23.42.108
Envelope sender = me@island.others.com
Reverse DNS of 16.23.42.108 = domain in PTR zone = others.com The domain of the sender (island.others.com) is a subdomain of others.com, and therefore we have an authentication.

Using this extra bit of authentication allows Gmail to authenticate almost twice as much mail as a standard SPF check. That’s actually pretty good. As to whether or not this is a good idea, OpenSPF has this to say about it:

Best-guess processing is a crude, non-standard attempt at guessing the IP address range of a domain’s outgoing mailservers. “Non-standard” means it is not standardized and specific to the implementation. … Some find this remarkably good at detecting unforged messages from domains that have not yet published SPF records. Others consider it a security hole because it gives attackers a lot of additional potential targets (authorized hosts) to hack in order to abuse the domain.

From an anti-spam perspective, I think sender authentication is a good idea but it all depends on how it is used. In my opinion, successful authentication is best used in conjunction with safe senders. I first voiced my opinion a few weeks ago when I thought it was a security risk. However, at the time I don’t think I was thinking ahead; I think the way to implement a safelist is to allow a sender to be on a safelist (ie, bypass spam filtering) if the sender can be authenticated. That way, spoofing the sender doesn’t work and if they do start spamming, there’s a much more reliable paper trail.
Read More… (From Terry Zink’s Anti-spam Blog)

No Description
Read More… (From Al Iverson’s DNSBL Resource)