Protecting Your Domain with SPF and DKIM

Some time ago, I started taking an Information Security (InfoSec) class and it really got me to start thinking about security in the digital age. Several scenarios throughout the class are poised on the principle of physical security and identify spoofing - known as social engineering.

I've often though how this can be applied to the digital world, since there is only a virtual threat (virus attachment, phishing attempt), rather than a physical one (unauthorized access to a secure office, etc). One of the ways I've found to protect email transmissions is through the use of SPF records and DKIM.

Both of these methods are intented to secure email transmissions, but in very different fashions. Sender Policy Framework (SPF) records are critical in determining if a particular sender is spammy and directly affects the score assigned to a message by a spam filter. DKIM - DomainKeys Identified Mail - is a way of digitally signing an email message with a domain to verify its legitmacy. Let's take a look at how both of these work and how to get them running on your MTA.


As I mentioned before, SPF is a handy bit of information to use to combat an influx of spam. Since most spam filters will automatically check for the existance of an SPF record in your domain's DNS zone file, all you really have to do is create one. However, there's a few bits of information you'll want to take into consideration and understand before building your record, namely compiling a list of all servers that send email on behalf of your domain.

It's important to remember that when building your SPF record, you'll want to include all servers that send email. In some special circumstances (i.e., corporate environments), you might have your incoming mail server separate from your outgoing mail server. SPF is only concerned with outgoing mail, so keep this in mind. The idea is for a SPF record to be a published list of approved servers that are allowed to send email on behalf of your domain. This helps spam filters sort the ham from the spam by determining which emails are legitimately from your domain and which have spoofed headers. Since there's no legitimate (read: non-malicious) need to spoof a mail header, anything that is spoofed is factored into a spam filter's assigned score.

There's a lot of good information on pertaining to syntax and the proper way to construct your SPF record. I strongly suggest you stay away from 'wizards' or 'generation tools' that help you build your SPF record. I'd rather you ask someone who is knowledgeable on the subject than use a tool that, in most cases, will add more pain to the process than is necessary. Wizards that create the record for you are, in my experience, highly unreliable for two reasons: 1) you can't guarantee that what it's building is correct, because you don't know the syntax, and 2) you learn nothing from the process. Building your record by hand is a matter of grokking the syntax, nothing more.

Now for the fun part: the meat of the record.

If you do dig txt from your favorite command-line tool, you should get a result back that looks like this:

;; ANSWER SECTION:    299 IN  TXT "v=spf1 ip4: ~all"  

Since spam filters use SPF records to determine if a particular sender is legitimate (and in turn, the message is legitmate), it will compare the sender's IP address and MTA hostname to what is specified in the SPF record. If the information in the mail message header doesn't match the specified values for the a, mx, or include mechanisms, then the ~all mechanism tells the spam filter to factor this result to the overall score, in addition to its other filtering processes. As I stated before, failing a SPF check doesn't automatically make the message spam, but it does weigh heavily into the overall score.

You'll always see a +, -, ~, or ? before the all mechanism and sometimes before the a, mx, ip4, etc. mechanisms. (EDIT: RFC 7208 obsoletes the qualifier syntax before a, mx, ip4, etc. but not before all.)

This leading character is what's known as a qualifier and tells the spam filter how to process the information attached to it. Think of this string of commands like a pop quiz: each mechanism is checked for a true/false response and the next mechanism is checked in the same fashion, until arriving at the all mechanism. If none of the previous mechanisms result in a true statement (known as a hit), than the all mechanism takes over. This mechanism is a catch-all and always matches if the other's don't. To state all of this in another way, if I were to send you an email message and your spam filter checks for SPF records, it would check the sending IP address against the SPF record ipv4 mechanism, see the match, and factor this hit into the overall score assigned by the filter.

A properly constructed SPF record can make a big difference in how your email is processed by the receipient's MTA. The last bit of advice I can impart on the subject is that it makes no difference whether your DNS host allows you to set a specific SPF record or not. Some DNS providers will allow you to create a specific SPF record. If you can't create the SPF record itself, you can put the same information into a TXT record and a spam filter will do the lookup the same way. The reason for this is when the Sender Policy Framework was first created, rapid proliferation of the framework was decidedly more important that creating a specific record type for it. Some providers have not yet chosen to support the specific code 99 record type as outlined in RFC 4408:

It is recognized that the current practice (using a TXT record) is not optimal, but it is necessary because there are a number of DNS server and resolver implementations in common use that cannot handle the new RR type. The two-record-type scheme provides a forward path to the better solution of using an RR type reserved for this purpose. An SPF-compliant domain name SHOULD have SPF records of both RR types. A compliant domain name MUST have a record of at least one type. If a domain has records of both types, they MUST have identical content.

To find out if your DNS provider is SPF-compliant, check with your domain registrar, hosting company, or whomever is hosting your DNS records.


DKIM - or DomainKeys Identified Mail - is a different beast altogether. Its function is to digitally sign your outbound emails with your domain, allowing you to claim responsibility for the message. It does this through a cyptographic process of generating a public and private key set: the private remains on your mail server and the public is what's added to a TXT record in your DNS zone file. Your public key will look something like this: 299 IN TXT    "v=DKIM1\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChE5Q25P2QuKVOJdnHTguezYx3pVcWVqVO3KkV8rieeQ+rBU8iZllRU5WIL+UVFdGO+TOjpqwkoa3gpSqykTB+PEHcPcSz5vF6t+PhIGTgcoJGOKs/5Hll3Fc5svzCYAfqQRSnac8h7Xb2C6QPkHc5SdwpjRODy7z4o24LUPJuOwIDAQAB"  

This string, is comprised from a 1024-bit private encryption key, which is generated from your mail server. The TXT record with this public key is requested by the recipient's mail server when verification of the domain is performed. Unlike S/MIME certificates, there is no expiration, revokation, or identity verification process to worry about, making DKIM one of the more self-contained methods of verifying an email sender's identity.

Creation of the keys is critical to the success of DKIM validation by SMTP servers, however, they're pretty easy to generate. In fact, it took me about 15 minutes from start to finish to generate mine. Since my server is running Mac OS, I'll show you the method I used, but note that a similar method could be used for Linux distros.

First, you'll want to create your DKIM private key. On your OS X mail server, run:

sudo amavisd genrsa /Library/Server/Mail/Config/amavisd/dkim_key  
sudo chmod 644 /Library/Server/Mail/Config/amavisd/dkim_key  

Next, you'll want to modify your amavisd.conf file. Best to make a copy before you, lest you bork something in between. You'll want to add the following line to your configuration, swapping out for your domain:

dkim_key('', 'mail', '/Library/Server/Mail/Config/amavisd/dkim_key'); @dkim_signature_options_bysender_maps = ( { '.' => { a => 'rsa-sha256', ttl => 30*24*3600, c => 'relaxed/relaxed' } } );  

And change the following line:

$interface_policy{'10026'} = 'ORIGINATING';


$interface_policy{'10024'} = 'MYNETS';

Save and exit out of your text editor. Now it's time to generate the DKIM public key you'll wind up entering into your DNS TXT record:

sudo -u _amavisd -H amavisd -c /Library/Server/Mail/Config/amavisd/amavisd.conf showkeys  

It will spit back your public key in the response. This is what you'll enter into your TXT record. Now, all you have to do is reload amavisd with:

sudo ps aux | grep amavisd | grep master  
sudo kill <PID#>  

As long as you're not deathly afraid of the command line on an OS X or Linux box, this process should be fairly straightforward. In no time, you'll have DKIM running on your server, digitally signing every email you send out with your domain, verified with some crypto-magic.

Of course, one important cavaet does exist. From a forensic standpoint, any email sent from your mailserver is your responsibility. This means that if someone does manage gain unauthorized access your mail server (or your email account) and sends a flood of spam or worse, it will be as if you yourself were sending it, making things pretty tricky to disavow in a court of law. Also, the european standard of using DKIM to verify identity in the case of legal documents requiring a signature may make you legally bound to the terms of an agreement. Of course, this is my educated inferences speaking, and I nothing I've previously said constitutes the legal advice. Don't be a dummy, consult a lawyer knowledgeable in the legal ramifications of digital signatures.


By now, you've read the long of it. The short of it is that by using SPF and DKIM on your mail server, you've managed to implement two widely accepted methods of digital verification of legitimate email, and helped prove your digital identity to SMTP servers. If you want to test your implementations of either of these methods, you can fire off an email to and you'll get a reply back within (usually) a few minutes letting you know the success of your implementations. If you're successful, your reply will have something similar to this:

SPF check: pass
DomainKeys check: neutral
DKIM check: pass
Sender-ID check: pass
SpamAssassin check: ham

This is exactly the result I received after implementing SPF and DKIM.

Happy (verified) emailing!