Setting up DKIMproxy with Exim for DKIM and DomainKeys signing
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
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
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
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
# openssl genrsa -out private.key 1024 # openssl rsa -in private.key -pubout -out public.key
Testing
You can test it by sending an email to:
check-auth@verifier.port25.com
Troubleshooting
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