Setting up DKIMproxy with Exim for DKIM and DomainKeys signing

From lxadm | Linux administration tips, tutorials, HOWTOs and articles
Jump to: navigation, search

Was your mail ever rejected or tagged as spam because it didn’t have a DKIM signature? You could enable DKIM-signing in Exim, but then, some older mail systems may still use DomainKeys.

Currently, Exim does not support signing mails with both DomainKeys and DKIM. You have to pick one of them, unless you do some tricks with patching Exim or connecting back to itself.

Still though, such setup is not perfect: Exim does not wrap its DomainKeys signature, which may result in SpamAssassin installations tagging your mail with HEAD_LONG rule (“Message headers are very long”) and assigning it 2.5 spam points.

So how to sign mail with DKIM and DomainKeys without negative consequences of being tagged by SpamAssassin for very long headers? DKIMproxy to the rescue!


Exim configuration[edit]

Exim should listen on an additional port – make sure you have something similar in your exim.conf file:

local_interfaces = 0.0.0.0 : 127.0.0.1.10025

Exim should speak TLS only on port 25, otherwise, it won’t be able to communicate with DKIMproxy:

tls_advertise_hosts = 0.0.0.0.25

at the beginning of the routers section in exim.conf:

dkimproxy:
driver = manualroute
condition = "${if eq {$interface_port}{10025} {0}{1}}"
transport = dkimproxy_smtp
route_list = "* localhost byname"
self = send

transports section in exim.conf (does not matter where):

dkimproxy_smtp:
driver = smtp
port = 10027
allow_localhost


DKIMproxy configuration[edit]

Download and install DKIMproxy (“./configure; make; make install” after you downloaded and extracted dkim-proxy package, unless your distribution provides it packaged).

Create a /etc/dkimproxy/dkimproxy_out.conf file with similar content:

# specify what address/port DKIMproxy should listen on
listen 127.0.0.1:10027

# specify what address/port DKIMproxy forwards mail to
relay 127.0.0.1:10025

# specify what domains DKIMproxy can sign for (comma-separated, no spaces)
domain host.example.com,example.com

# specify what signatures to add
signature dkim(c=relaxed)
signature domainkeys(c=nofws)

# specify location of the private key
keyfile /etc/dkimproxy/dkim.key.private

# specify the selector (i.e. the name of the key record put in DNS)
selector default

Make sure DKIMproxy is started when your server boots (add it to your startup scripts):

/usr/local/bin/dkimproxy.out --conf_file=/etc/dkimproxy/dkimproxy_out.conf --daemonize

Place the private key you want to use with DKIMproxy in /etc/dkimproxy/dkim.key.private. If you use cPanel, you may symlink it to a key in /var/cpanel/domain_keys/private/.


DNS configuration[edit]

Similar entries will be needed in your DNS zone configuration:

default._domainkey 14400 IN TXT "k=rsa; p=MH.........;"
_asp._domainkey.example.com. IN TXT "dkim=unknown"
_adsp._domainkey.example.com. IN TXT "dkim=unknown"
_domainkey.example.com. IN TXT "t=y; o=~;"


Key generation[edit]

# openssl genrsa -out private.key 1024
# openssl rsa -in private.key -pubout -out public.key


Testing[edit]

You can test it by sending an email to:

check-auth@verifier.port25.com


Troubleshooting[edit]

If you use cPanel, you will see such entries in your /var/log/exim_mainlog:

socket bind() to port 10025 for address 127.0.0.1 failed: Address already in use: waiting 30s before trying again

This is because /etc/init.d/exim script shipped with cPanel starts two instances of Exim, one of them is listening on port 465 – SMTP over SSL (TLS), but reading the same config file. This conflicts with “local_interfaces = 0.0.0.0 : 127.0.0.1.10025“. Second instance of Exim will try to bind to port 10025 as well, but will give up after 10 tries.

To fix it, add this to your Exim config file:

daemon_smtp_ports = 25 : 465
tls_on_connect_ports = 465


And comment out these lines from /etc/init.d/exim:

echo -n "Starting exim-smtps: "
# TMPDIR=/tmp $DAEMONIZE /usr/sbin/exim -tls-on-connect -bd -oX 465
# echo $RESULT