DKIM with Postfix on Debian wheezy

DomainKeys Identified Mail is a method that allows an MTA to add a signature to outgoing mails. The receiving MTA can validate the signature using a key published in the sender's DNS records. This page outlines how to configure opendkim with Postfix on Debian wheezy. The setup is similar to one described in the document DKIM on Debian Wheezy with minor changes. Most notably, the setup described here uses a UNIX socket for the Postfix-to-opendkim communication rather than a TCP port. This is marginally more secure as it doesn't create a potential remote attack surface as a TCP port would.

First, install the opendkim packages:

opendkim                  Milter implementation of DomainKeys Identified Mail
opendkim-tools            Set of command line tools for OpenDKIM

Configuring opendkim

Edit /etc/opendkim.conf and add the following lines. This page describes a multi-domain setup, hence the KeyTable option is used, which has a precedence over the KeyFile option.

ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts           refile:/etc/opendkim/TrustedHosts
KeyTable                refile:/etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable

UserID                  opendkim:opendkim

# Postfix runs in a chrooted environment under /var/spool/postfix:
Socket                  local:/var/spool/postfix/opendkim/opendkim.sock

Edit /etc/opendkim/TrustedHosts and add your trusted domains and IP addresses. These hosts may send mails through this system without credentials.

127.0.0.1
localhost

*.example.com
*.example.net

Next, create the Key table /etc/opendkim/KeyTable which maps the key names to a signing key.

key.for.example.com example.com:mailYYYYMMDD:/etc/opendkim/keys/example.com/mailYYYYMMDD.private
key.for.example.net example.net:mailYYYYMMDD:/etc/opendkim/keys/example.net/mailYYYYMMDD.private

Finally set up the signing table /etc/opendkim/SigningTable. This file maps addresses or domains to one or more signatures.

*@example.com key.for.example.com
*@example.net key.for.example.net

For each domain, create the key in a separate directory using the opendkim tool. The option -d specifies the domain. The -s option specifies the selector, which is the string before the fixed _domainkey domain part. The DNS resource record selector._domainkey.example.com will be queried by the mail recipient to validate the DKIM signature.

I suggest to choose a form like mailYYYYMMDD as a selector where YYYYMMDD is the current date. This makes it easy to add a new key in the DNS record and still use the old key in Postfix while the change slowly trickles through the various layers of DNS caches.

mkdir -p /etc/opendkim/keys/example.com
opendkim-genkey -D /etc/opendkim/keys/example.com/ -s mailYYYYMMDD -d example.com
chown opendkim: /etc/opendkim/keys/example.com -R

This command creates two files, mailYYYYMMDD.private and mailYYYYMMDD.txt. The former file contains the key and is to be kept secret, and the latter file is a DNS TXT record which needs to be copied to the DNS configuration for the domain. Below is an example of the mailYYYYMMDD.txt file. Copy everything in quotes to the DNS TXT record with name mailYYYYMMDD._domainkey.

mailYYYYMMDD._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2hL+x3IXwY9a1n/UWnumT2K5TZF/UT2bb5tV15acgj6PyFcQhfG0OjJABhwkOsyR3g3qzFXiMqQAdR9qnzAd0PGFk8DQT xKyloNoLIV5wbVXyTDtnTYdGiNhfQmhaS9VmUkN7YKGZ9s8PlF6OlDoT1Yo+Fhr I5jj0Sna6cmppYwIDAQAB" ; ----- DKIM key mailYYYYMMDD for example.com

Please allow a few hours for the various DNS servers to refresh their cache before configuring Postfix.

Configuring Postfix

Edit /etc/postfix/main.cf and add the following line that tells Postfix to handle milter errors gracefully.

milter_default_action = accept

If the DKIM milter is the only in use, then add also the following lines:

smtpd_milters = unix:/opendkim/opendkim.sock
non_smtpd_milters = unix:/opendkim/opendkim.sock

Otherwise, if there are already some milters configured, then simply add the opendkim milters to the existing lines, e.g.:

smtpd_milters = unix:/spamass/spamass.sock, unix:/opendkim/opendkim.sock
non_smtpd_milters = unix:/spamass/spamass.sock, unix:/opendkim/opendkim.sock

Also add a milter_connect_macros option:

milter_connect_macros = j {daemon_name} v {if_name} _

Make sure the directory /var/spool/postfix/opendkim exists and is writable by the user opendkim. Also add the postfix user to the opendkim group so it can read the socket:

mkdir -p /var/spool/postfix/opendkim
chown opendkim:opendkim /var/spool/postfix/opendkim/
usermod -a -G opendkim postfix

On Debian Wheezy, the path to the opendkim.sock is hard coded in the file /lib/systemd/system/opendkim.service. Change the argument to the -p option to /var/spool/postfix/opendkim/opendkim.sock and restart systemd:

systemctl daemon-reload

Finally, restart opendkim and Postfix and you're done.

service opendkim restart
service postfix restart

Increasing the header size for opendkim

Sometimes mails get rejected and you see messages like the one below in your log.

U Wed Dec  7 04:32:55 2016 5 opendkim.service opendkim[3493]: too much header data

This means the header exceeds the built-in size limit in opendkim. You can increase this limit with the following setting in your /etc/opendkim.conf file.

MaximumHeaders          262144

A value of 0 disables the size limit altogether.

Updates

7 December 2016
Added the MaximumHeaders setting and reformulated some sentences.
24 June 2015
Fixed problems with missing /var/spool/postfix/opendkim and access rights to it. Thanks to Milivoj.