DKIM and postfix

Had some fun installing DomainKeys Identified Mail (DKIM for short) at work today and seeing as I had some problems I figured I'd detail my experiences here, for future reference.

Short intro

The basic idea in DKIM is to be able to show that a given email message came from a specific domain. In a way, it's like SPF but in reverse: where SPF says that a given IP address is allowed to send e-mail (or not allowed) for a specific domain, DKIM will state that a given e-mail originated from a specific domain. Both technologies involve DNS - you need to publish DNS records that a receiving server can use to check that the message received is legit. The point being that if you can show control over DNS records for the relevant domain, you gain a certain amount of trust (as presumably not anyone can edit records for a given domain).

Whereas with SPF all you need to do is create a TXT record, with DKIM you'll need to setup some software. This is because DKIM creates a signature of the e-mail sent and adds this signature as a header to the e-mail. A receiver can then check that this signature is valid, upon receipt, and thus make sure that the e-mail is legit.

Installation

I was working on a Debian Squeeze server, and the first of my worries came from trying to install the two packages needed for the setup. Essentially you want to install opendkim and opendkim-tools

apt-get install opendkim opendkim-tools

However, this gave errors about broken dependencies. The reason turned out to be that opendkim was offered from Squeeze but opendkim-tools was only found in Squeeze-backports. The two packages are incompatible with one another (surprise!). The solution was to install the opendkim package by specifying the newer version on the command line, so that both packages got installed from Squeeze-backports.

apt-get install -t squeeze-backports opendkim opendkim-tools

This got the needed packages installed - so onto the next bit.

Configuration

Assuming a Debian installation, you'll now have an /etc/opendkim.conf and an /etc/default/opendkim file. To this, we'll add a directory for opendkim files (mainly private keys and some lookup tables). So

mkdir -p /etc/opendkim/keys chown opendkim:opendkim /etc/opendkim -R

Next, edit /etc/opendkim.conf, and make sure the following bits are set

UserId opendkim:opendkim KeyTable /etc/opendkim/keytable SigningTable /etc/opendkim/signingtable ExternalIgnoreList /etc/opendkim/trustedhosts InternalHosts /etc/opendkim/trustedhosts

In the setup/debug phase, you should use the following settings to help narrow down problems:

LogResults Y LogWhy Y

Save opendkim.conf and edit /etc/opendkim/trustedhosts to contain

127.0.0.1 localhost

Save it, then edit /etc/opendkim/signingtable. Here, you put lines that specify a domain and the matching DNS record ID to request a TXT record from. So the form is

domain domain-key-dns

Stick in a line for every domain you need to sign e-mails for. Example for plind.dk

plind.dk dkim._domainkey.plind.dk

After saving this file, open up /etc/opendkim/keytable and edit it. Again, you want a line per domain to sign e-emails for - this time the format looks like:

domain-key-dns domain:selector:path-to-private-key

The private keys haven't been created yet, but that doesn't matter - set up a proper naming scheme for them now and stick to that, then you can create keys before or after editing this file as you prefer. Example of a keytable file for plind.dk

dkim._domainkey.plind.dk plind.dk:dkim:/etc/opendkim/keys/plind.dk/dkim.private

After editing this file, it's time to create the actual keys. CD into /etc/opendkim/keys, create a directory per domain, then in each of the domains run the following:

opendkim-genkey -r -h sha256 -d domain -s selector

Make sure to replace the domain with what you want to create keys for, and the selector to match your setup. Also, make sure that you put in 'sha256' as the value for -h - I saw a couple of places online that used rsa-sha56, which is invalid and might give you problems.

Example for plind.dk

opendkim-genkey -r -h sha256 -d plind.dk -s dkim

This generates a selector.txt and a selector.private file (substitute selector with whatever you provided on the command line). From the selector.txt file, you'll find the contents you need to create a DNS record with. Remember, you need to create a TXT record for a domain named like selector._domainkey.domain - so, using plind.dk as example domain and dkim as selector, it would be dkim._domainkey.plind.dk.

When you create the TXT record, you only need to supply the content within the quotation marks - leave the rest out.

After creating the private key with opendkim-genkey, step out on directory and chown the folder and the files to opendkim - and make sure that only dkim can read and write the files.

Then, lastly, it's time to edit /etc/default/opendkim to set details of how opendkim can be connected with. I opted for a unix socket as they are generally faster then TCP sockets, and we handle a fair amount of email.

To set this, uncomment the line in your /etc/default/opendkim file that looks like SOCKET:local:/var/run/opendkim/opendkim.sock - rename the path as needed here.

Two things to keep in mind if you do this: if you try to connect postfix and opendkim, you need to have opendkim create it's socket somewhere that postfix can access it, which most likely means in /var/spool/postfix as postfix will probably run chrooted. I created an opendkim directory right under /var/spool/postfix, to put the socket in. The second thing to keep in mind is handling permissions for the socket. I found I needed to set the socket to 0777, before postfix could access it properly. To support this, you'll also need to change the UMask setting in /etc/opendkim.conf. After taking care of both, I could get postfix to successfully connect to opendkim.

Lastly, restart opendkim and make sure that it's running - that way  you'll know if you made any mistakes along the way.

Connecting to postfix

To have postfix connect to opendkim, you need to set a couple of settings in /etc/postfix/main.cf. Specifically, edit the file to include these:

milter_default_action = accept milter_protocol = 6 smtpd_milters =unix:/path/to/socket non_smtpd_milters = unix:/path/to/socket

Remember that the path to the socket is relative to the chroot of postfix, if it's running chrooted.

Finally, restart postfix to refresh the configuration, then try to send e-mail with one of the domains you set up keys for. Try sending it to a Gmail account (you should some extra info displayed for the e-mail) or use www.mail-tester.com to check that a DKIM was added properly.

In case you experience problems, use the debugging settings of opendkim and check the syslog for error messages.

social