SPF to avoid spoofing

If you are tired of faked emails from popular domains like eBay or Paypal then there is hope. And you can even protect your own domain from spammers sending in your name. It is about SPF which is short for sender policy framework. Basically  the owner of a domain defines which IP addresses are allowed to send email. Let's take an example. If you have the dig tool around then run…

$> dig +short workaround.org txt

and you should see something like

"v=spf1 ip4:85.214.93.191 ip4:85.214.149.150 -all"

This entry means that if someone sends you an email with a sender email address of …@workaround.org then you should only accept it if it was sent from one of these two IP addresses. The "-all" at the end tells you that no other IP addresses should be accepted (FAIL). Another definition like "~all" means a SOFTFAIL - you should at least be suspicious and perhaps increase the spam score. (Actually "~all" is widely used but pretty useless. Either you know what you are doing and use "-all" or leave it off entirely. If you want to test if SPF workd then you could use "?all".) So if someone sent you an email from …@workaround.org from another IP address then you should drop it - it's spam.

Many organisations already have SPF records that you can use to reduce the amount of spam you receive. So your duties as a mail server administrator are:

Set up an SPF entry

Obviously you need to have full control of your DNS zone to add a TXT record. If you don't then speak to your ISP and let them add the TXT entry. The SPF record needs to be properly machine readable. I suggest you go to the OpenSPF web site and use their wizard to create a proper SPF entry. Add this string as a TXT record for your domain. Just like above you should get the SPF entry back if you run:

$> dig +short mydomain.com txt

You need to be aware of one caveat though which is also SPFs biggest problem: if your users forward the email somewhere else then it might get rejected. By all means you need to be sure that your users always send email just through your mail server.

Check other mail servers' SPF entries

Fortunately there is a Debian package for the tumgreyspf software which makes checking SPF entries easy. Just install it:

$> apt-get install tumgreyspf

tumgreyspf is a policy daemon written in Python that does both greylisting and SPF checking of incoming emails. Using it is detailed in the /usr/share/doc/tumgreyspf/README.Debian file. Basically it boils down to adding one line to your smtpd_sender_restrictions (or smtpd_recipient_restrictions if you put everything in there) making use of it. Example:

smtpd_sender_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    [ ... ]
    check_policy_service unix:private/tumgreyspf
    [ ... ]
    permit

And to define the program that is called when using this policy service you need to add two lines to your /etc/postfix/master.cf:

tumgreyspf unix  -      n       n       -       -       spawn
    user=tumgreyspf argv=/usr/bin/tumgreyspf

Now reload your Postfix and that's it:

$> postfix reload

Case: SPF okay

Watch your /var/log/mail.log logfile. Every incoming email should now log an additional line from tumgreyspf. If the SPF check was positive then you will get:

tumgreyspf[24672]: sender SPF authorized: QUEUE_ID=""; identity=mailfrom;
   client-ip=26.21.244.31; helo=squedge2.squ.edu.om;
   envelope-from=…@squ.edu.om;
   receiver=…@workaround.org;

This means that the sender …@squ.edu.om was allowed in after checking the SPF entry.

Case: SPF fail

If the SPF check fails then you will see something like:

tumgreyspf[24672]: SPF fail - not authorized: QUEUE_ID=""; identity=mailfrom;
   client-ip=41.234.18.141; helo=gmx.de;
   envelope-from=…gmx.de;
   receiver=…christoph-haas.de;

The email got rejected. One spam mail less in the world. :)

Case: SPF softfail

The third case is when the SPF entry does not enforce a FAIL (-all) but just uses SOFTFAIL (~all). In your log file it will look like:

tumgreyspf[20408]: domain owner discourages use of this host: QUEUE_ID="";
   identity=mailfrom; client-ip=220.245.2.67; helo=220-245-2-67.static.tpgi.com.au;
   envelope-from=…@rollouts.com; receiver=…@workaround.org

Unfortunately the SOFTFAIL does not actually reject the email. But the sender still believes that this IP address should not be sending email in their name. Luckily tumgreyspf adds this information to a "Received-SPF" header into the email. Just like:

Received-SPF: Softfail (domain owner discourages use of this host) identity=mailfrom;
   client-ip=61.146.93.243; helo=mail.163gd.com;
   envelope-from=…@cantv.net; receiver=…@christoph-haas.de;

So you still have a chance to mark such emails in spam in your email client by filtering out emails having a "Received-SPF: Softfail" header.

(Unfortunately tumgreyspf does not have a configuration option to treat SOFTFAIL as FAIL.)

Case: No SPF information

If the remote domain is ignorant and stupid and does not have any SPF entries yet then your log file will read:

Received-SPF: Neutral (access neither permitted nor denied) identity=mailfrom;
   client-ip=80.65.65.222; helo=mail.unze.ba;
   envelope-from=…@gmail.com; receiver=…@christoph-haas.de;