Wednesday, June 9, 2010

Setting up DKIM, SPF, Domainkeys DNS, Regular DNS on CentOS

SkyHi @ Wednesday, June 09, 2010

I'm working with one site that is struggling with mail being rejected outright by other mail servers and sent to the spam box. Over the past month, I've fixed a few errors in the MIME formats, contacted rejecting domains (aol, live, yahoo, etc), all of which has increased slightly the success rate on mail delivery. But not enough. So the next step has been to setup the signature pages so that the site can sign mail and no spammers can take advantage of the good reputation the site builds. This is no guarantee, of course, but it's the next logical thing to try.

The first step was to setup postfix. Although I had managed to get sendmail running fairly well, it was not fun. Adding in the DKIM signatures would have probably been even less fun. So I switched the server over to using postfix, which was easy as a charm. (http://wiki.centos.org/HowTos/postfix)

Because the site needs to be able to sign mail from POP clients for exactly one username, I set up that user with no login shell, but I configured postfix to accept mail from that single user. Any other users or domains - relay rejected. I tried to set that SMTP connection up as a secure connection to protect the password etc (http://www.linuxmail.info/smtp-authentication-postfix-centos-5/) but ran into a couple stumbling blocks and for the moment it's not as important to continue with that - I might look into it later again. I did not turn on pop/imap - only smtp - and only for that one user with no login shell so I'm not too stressed about the plaintext password. (Did I mention that I backup all my sites every hour?)

Next, SPF. The 'Sender Policy Framework" is a record that the domain name owner can publish that gives receiving spam-sorters an idea about who you want to be able to send mail from your domain. (See http://www.openspf.org/Project_Overview, http://www.zytrax.com/books/dns/ch9/spf.html, http://www.openspf.org/Test_Suite, and http://tools.bevhost.com/spf/) In my case, I made a very restrictive spf "v=spf1 a -all" that allows mail to be sent only from the main domain example.com.

Following these two guides, I added dkim to the postfix configuration:

http://www.howtoforge.com/set-up-dkim-on-postfix-with-dkim-milter-centos-5.2

Unfortunately, at that point, I learned from emailing with name.com support that my domain name registrar name.com does not support the <>._domainkey txt record... so I was forced to set up my own nameserver.

After some comparisons, I chose to setup named/bind. (http://www.howtoforge.com/creating-your-own-webserver-with-bind-and-apache-centos5) I am running it chroot'ed (http://www.wains.be/index.php/2007/12/13/centos-5-chroot-dns-with-bind/), and I'm running it only as the master zone for my domain example.com, having turned off the normal nameserver functionality of reciprocal queries. Here's the syntax for the zone file: http://centos.org/docs/5/html/5.2/Deployment_Guide/s2-bind-zone-directives.html. Another good dns/bind reference.

All this amounted to more than one day's work, because it was my first time setting up these systems. Unfortunately, the mail was still receiving dkim=permerror (better than the dkim=neutral from before... as long as it doesn't last forever!) ... which I found was in part due to my server's time being *15 minutes slow* (dig the dryptic message dkim=permerror (verification error: signature timestamp in the future) !! ) -- So to solve this problem once and for all, "yum install ntp ; chkconfig ntpd on ; date ; ntpdate pool.ntp.org ; date ; service ntpd start"

voila - emails doubly signed by SPF and DKIM. Verified by sending to google email address (then show detailed headers) and also by sending to

  1. sa-test@sendmail.net
  2. autorespond+dkim@dk.elandsys.com .

Final step was adding in additional domainkey authentication to make yahoo particularly happy. It's almost identical to dkim. Yahoo, being in the dark ages, still uses it. So http://www.topdog.za.net/postfix_domainkeys_milter

You'll have to add multiple milters in the configuration of postfix to handle both dkim and domainkeys. Here's the end of my postfix config file:

smtpd_milters = inet:localhost:20209 unix:/var/run/dk-milter/dk.sock
non_smtpd_milters = inet:localhost:20209 unix:/var/run/dk-milter/dk.sock

I used a different selector for the domainkey. At first I tried to use the identical selector and keys, but couldn't get it to work although it is probably possible; when I tried just setting it up with a different selector both yahoo (domainkeys) and gmail (dkim) were happy.
I also sent a testemail to autorespond+dk@dk.elandsys.com which verified the domainkeys configuration as well.
Oddly enough, though all tests from the command line indicated proper setup, when sending mail from php's native mail function, and from the script's pseudo-native use of postfix's sendmail proxy, the domainkey was signed incorrectly. Since my script had an option to send through SMTP, I just directed it to the SMTP port on localhost, and this worked to get around the problem.

The one thing that I did not yet address is that we are now supposed to publish SPF both in the TXT field and in the SPF field. With my version of named/bind, I am getting an unknown RR type when I include the SPF in my zone file, so for now I have commented it out. Any tips on what might be the cause of that? Google definitely gets the "terrible results" prize for that query, as it is overvaluing the old specification documents rather than any recent, useful discussion of the error.

Finally, you also need to investigate the history of your specific IP and get your reverse DNS information set properly. To investigate some aspects of your IP address and its characteristics, take a look at Microsoft's Smart Network data services (for delivery to live/hotmail), http://www.senderbase.org/, and Yahoo http://feedbackloop.yahoo.net. Good luck.


REFERENCES
http://palma-seo.com/setting-dkim-spf-domainkeys-dns-bind