What is DKIM?

DKIM or DomainKeys Identified Mail is an email authentication system that can help prevent spoofing by signing outgoing mail. More information can be found on Wikipedia or Google.

DKIM uses a private and public key pair for signing, the public key is stored in a TXT record in the DNS zone, similar to SPF.

Simple setup on Ubuntu 14.04

Install OpenDKIM

sudo apt-get install opendkim opendkim-tools

Generate a private and public key pair

opendkim-genkey -t -s default -d example.com

The -s switch defines the name of a selector, it's used later in both configuration on the server and the TXT record.

This generates 2 files, based on the name of the selector, e.g. default.private and default.txt

Add the TXT record

The txt file created by opendkim-genkey uses a bind record format and looks something like this:

default._domainkey	IN	TXT	( "v=DKIM1; k=rsa; t=y; "
  "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbpMiQR1EMmOmCYzzuHYlXho97NnX1/nFCftJLjY2NVkGlCdxMpnnoVI3oGeM1DmzdbC9eySW+GbFnPs0FrPB5Tqod1XXYI3gwrMihIyMJfsIMAU0EPJKvJjwsELNYj4UHWBhWIjusGw0AeDQuUH0sCYOkdPkOSvM2wpZsvHkDZwIDAQAB" )  ; ----- DKIM key default for example.com

You can extract the necessary information from here to use with most registrars or DNS services.

Record name

The record name should be ._domainkey prefixed with the selector name:

default._domainkey.

Any sub domain information should be appended, which opendkim-genkey doesn't do. for sub.domain.example.com you should use:

default._domainkey.sub.domain

TXT value

The value should include a minimum of the DKIM version, key and key type:

v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbpMiQR1EMmOmCYzzuHYlXho97NnX1/nFCftJLjY2NVkGlCdxMpnnoVI3oGeM1DmzdbC9eySW+GbFnPs0FrPB5Tqod1XXYI3gwrMihIyMJfsIMAU0EPJKvJjwsELNYj4UHWBhWIjusGw0AeDQuUH0sCYOkdPkOSvM2wpZsvHkDZwIDAQAB

Configure OpenDKIM

On Ubuntu the config files OpenDKIM uses are:

/etc/opendkim.conf
/etc/default/opendkim

Copy the private key

Many guides suggest copying files into /etc/mail, but OpenDKIM complains about permissions and won't start so it was easier to create a new folder in /etc and copy it there:

sudo mkdir /etc/opendkim
sudo cp default.private /etc/opendkim

Update /etc/opendkim.conf

As a minimum the domain, key path and selector are required:

Domain                  example.com
KeyFile                 /etc/opendkim/default.private
Selector                default

Update /etc/default/opendkim

Ubuntu uses a socket by default, but Sendmail complains that this is insecure so it's necessary to use a port instead, the following can be appended to the end of the file:

SOCKET="inet:8891@localhost" # listen on loopback on port 8891

Start the service

sudo service opendkim start

Configure Sendmail

Update the configuration

Append the following to /etc/mail/sendmail.mc:

INPUT_MAIL_FILTER(`opendkim', `S=inet:8891@localhost')

Regenerate the Sendmail config file as root:

sudo -i
m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf

Restart the service

sudo service sendmail restart

Checking everything works

From server logs

By default OpenDKIM logs to the syslog, so you can tail the log to see if signing is successful using:

sudo tail -f /var/log/syslog | grep -i dkim

You should see something like this example taken from one of the web servers that host this blog:

Mar 16 09:25:02 web2 sm-mta[7705]: u2G9P2Dp007705: Milter insert (1): header: DKIM-Signature:  v=1; a=rsa-sha256; c=simple/simple; d=web2.lon.codacity.net;\n\ts=linode; t=1458120302;\n\tbh=C8sxHQz0QeFsCiNzhPYF8u2GVHRax8cSsYISckkpuEk=;\n\th=Date:From:Subject:To:From;\n\tb=ymr4SQ67DqXBMkVPPfjTJUEWBPFpO4jix7oZXsranp6MQrzcXg8ysbwkL0+6VdcqA\n\t DrzTrz3O6SfVh9Aok6H+tGcPIb9jMGTn1ceLlAZhy18O5qmjkZOTHr2MWtKeaf1u2M\n\t FfBBOID4M9vef7FZBJaUa0j+Zg9LarLaYW518TEo=

From your mail client

View the source of an email sent from your server and look for the Authentication-Results header. It should contain dkim=pass if everything is working. There is also a DKIM-Signature header which contains the signing data.

Further steps

This guide will get you up and running for a single domain, for multiple domains a few extra steps are necessary. I will update this post at a later date to include this.