Deploying DMARC (and DKIM)

I found that Google/Gmail was suddenly filing email from my domains into the spam folder of the recipients. At that point I had implemented SPF a few years back. It's difficult to access whether SPF pass increases the chances for successful delivery, but SPF fails definitely increase the odds of rejections, which is a good thing, because it makes my domains unattractive for spoofing. This in turn has reduced the number of non-delivery messages (back-scatter) for spam that claimed to originate from one of my domains to just about none.

At that point I didn't provide DomainKeys nor DKIM signatures on my mail server, simply because doing so seemed like an effort with little measurable benefit, and thus it would be difficult to tell even whether any implementation attempt would result in correct behavior. This was the frustrating part of the Gmail situation: because of the shoot-and-forget nature of email, it was impossible to find out why my mail was filed as spam, and I only became aware of the problem after anecdotal evidence from recipient users who ultimately found my emails in their spam folders, after they had kept claiming that they never received them for a long time.

Here's where DMARC came in: it provides a mechanism for me as the administrator of a small mail server (a few hundred outgoing emails per day) to get automated feedback about how my mail is received by the top email services. DMARC is easy to implement (comparable to SPF) and results in immediate benefits: Google, Microsoft, and Yahoo immediately started sending daily reports for each of my sender domains, reporting how many mails they had received from me and how these mails looked from their end.

However, these reports were in XML and quite tedious to interpret by hand. Enter dmarcian.com: they offer to collect and consolidate these reports and provide very powerful and easy-to-use analysis. A single screen shows you the health of all of your domains as seen from the perspective of the top email recipients, and you can easily drill down to every level of detail if you wish. This service is free for small guys like me — they hope to make their money from the big mail server operators, and I sure hope they do!

At the first level, DMARC just provides feedback, and this already helped me to find out that some of my SPF settings weren't quite right and let me fine tune them. And it persistently showed me that my DKIM was failing — of course, since I hadn't implemented it yet. So, the next step was to implement DKIM on my qmail server, along the lines of Kyle Wheeler's Qmail Patch Explanations and Recommendations and Lincoln Ritter's Setting up DKIM and Domainkeys Email Signing with QMail.

I use one mx for serving multiple domains, but these are all under my control, and I've decided to use the same key pair for all domains. This has considerably simplified deployment and works just fine.

The steps in detail (salvaged from the command line buffer):

mkdir -p /etc/domainkeys/mail.sscnet.ch/
cd /etc/domainkeys/mail.sscnet.ch/
mkdir libdomainkeys
mkdir dkim
wget http://sourceforge.net/projects/domainkeys/files/latest/download?source=...
wget http://garr.dl.sourceforge.net/project/domainkeys/libdomainkeys/0.69/lib...
wget http://www.cpan.org/authors/id/J/JA/JASLONG/Mail-DKIM-0.40.tar.gz
wget http://www.cpan.org/authors/id/J/JA/JASLONG/Mail-DKIM-0.40.readme
perl Makefile.PL
cd dkim/libdomainkeys/libdomainkeys-0.69
make
make test
make install
 
install -m 644 libdomainkeys.a /usr/local/lib/
install -m 644 domainkeys.h dktrace.h /usr/local/include/
install -m 755 dknewkey /usr/local/bin/
install -m 755 dktest /usr/local/bin/
 
mkdir -p /etc/domainkeys/mail.sscnet.ch/
cd /etc/domainkeys/mail.sscnet.ch/
 
 
install -m 755 scripts/dkimsign.pl /usr/local/bin/
install -m 755 scripts/dkimverify.pl /usr/local/bin/
 
 
ln -s qmail-remote.real qmail-remoteX
mv qmail-remoteX qmail-remote
 
cat - >qmail-remote-wrapper.sh

#!/bin/bash
DOMAIN="ua4net.sscnet.ch"
DKREMOTE="/var/qmail/bin/qmail-remote.real"
DKSIGN="/etc/domainkeys/$DOMAIN/default"
tmp=`/bin/mktemp -t dk.sign.XXXXXXXXXXXXXXXXXXX`
/bin/cat - >"$tmp"
 ( /usr/local/bin/dktest -s "$DKSIGN" -c nofws -h <"$tmp" 2>/dev/null | \
     /bin/sed 's/; d=.*;/; d='"$DOMAIN"';/' ;
     /usr/local/bin/dkimsign.pl --type=dkim --selector=default \
         --key-file="$DKSIGN" --method=relaxed <"$tmp" | \
         /usr/bin/tr -d '\r' ;
     /bin/cat "$tmp" ) | \
         "$DKREMOTE" "$@"
retval=$?
/bin/rm "$tmp"
exit $retval


openssl genrsa -out rsa.private 1024
openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
mv rsa.private default
chown -R qmailq /etc/domainkeys
chgrp qmail default
chmod 0640 default
grep -v ^- rsa.public | perl -e 'while(<>){chop;$l.=$_;}print "t=y; p=$l;\n";'
chmod a+x qmail-remote-wrapper.sh
/usr/local/bin/dktest
/usr/local/bin/dkimsign.pl