DKIM with Exim
Gmail recently blocked a legit email originating from my server. It seems they have again raised the bar to be able to use their services, and it's time to setup DKIM signing for my private server (running Exim4).
One of my last posts was about using Debian's mail-submit server
to get my @debian.org
emails signed with DKIM.
That post also explains the basics of DKIM, so I'm not going to recap them here.
In order to automatically sign all mails from my mailserver with DKIM, there are basically three steps required:
- create a DKIM certificate
- publish the public key via DNS
- setup Exim4 to sign the emails with the private key
Creating a DKIM certificate
A DKIM-certificate is just an RSA certificate, which can be created with openssl
.
Rather than doing that manually, we can use a the opendkim-genkey
utility
(conveniently available in Debian via the opendkim-utils
package).
We can specify the target domain via the --domain
flag (although this is mainly cosmetics),
and the selector via the --selector
flag (which is a mandatory setting with DKIM and important for managing keys over time).
While the value for the domain is obvious (and since this is going to be used for my private server, I'm using umlaeute.mur.at
),
the selector is an arbitrary string. For convenience I just pick the current date (at the time of key generation).
I'm quite fond of using subdomains for sending emails, so I'll throw in the --subdomains
flag to indicate that
my key is allowed to use that as well.
(For whatever reasons the utility is installed in /usr/sbin
, so if you are not running as root
,
you might need to specify the full path to the binary.)
1/usr/sbin/opendkim-genkey --domain=umlaeute.mur.at --subdomains --selector=$(date +%Y%m%d)
That's it!
This will create two files (named after the chosen <selector>
) in the current directory,
the private key (in my case 20221012.private
) and
the public key (20221012.txt
), the latter conveniently formatted as DNS TXT record.
Publishing the certificate via DNS
The next step is to publish the public key via DNS.
The TXT record needs to be made available under <SELECTOR>._domainkey.<DOMAIN>
(in my case that would be 20221012._domainkey.umlaeute.mur.at
).
The TXT record can be found verbatim in the public key file as generated by opendkim-genkey
(here: 20221012.txt
), and looks like this:
120221012._domainkey.umlaeute.mur.at. IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
2 "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA664STmgQrQ0SBYEuhAGQJZEP+4tUrhnY+VoO/9Jh/32FKDTF/ctsS6P33qBTvNkObdbWykKcqj/yOqYe7WmeiD+0IdHML2owyGXRtLmoHBplldPZ68FTQT20q+YD9orz8UeSXVdzzQHnYSj6Ytg0QkHa3N+Yu6ql9v8rQ7Yvb+wV7JCoHBoKRs62Wy3hWIQz6nuxTbIceZmnlE"
3 "TfX3c2BRu0TOZqEGfJKVNgcfvF/LsbPuPMoM2mlacHtpMmMtjrnDJGEmopvCl8Jv8VZkGNZRohrTMODc6EAVuvHvoQr4s+aANfhx+IHhrNyhRPnW/wZGy8X/2wb3F6kPsfh/uETwIDAQAB" ) ; ----- DKIM key 20221012 for umlaeute.mur.at
Since I do not operate the DNS-server for my private domain, I have forwarded the request to add the TXT record to the friendly staff at mur.at.
The current status of the TXT record can be queried with:
1dig TXT +noall +answer 20221012._domainkey.umlaeute.mur.at
Signing emails with Exim4
Once the DKIM public key is published in the DNS, it's time to setup the signing within Exim4 on my Debian system.
The basic Exim4 configuration that ships with Debian already comes with full support for DKIM, so we only need to tell it to actually use it by setting the following three variables:
DKIM_DOMAIN
the domainDKIM_SELECTOR
our chosen selectorDKIM_PRIVATE_KEY
the full path to the private key file (20221012.private
)
For this I put the private key into a directory /etc/exim/dkim/
on the mailserver, and renamed it to <DOMAIN>-<SELECTOR>.private.pem
(so it's really /etc/exim/dkim/umlaeute.mur.at-20221012.private.pem
).
However, I don't hardcode the name, but instead use the DKIM_DOMAIN
and DKIM_SELECTOR
variables (which are mandatory anyhow), to calculate it.
The following snippet goes into a newly created file /etc/exim4/conf.d/50_local-dkim
:
1################### DKIM ####################
2# enable DKIM signing of emails
3
4DKIM_DOMAIN = umlaeute.mur.at
5DKIM_SELECTOR = 20221012
6
7.ifdef DKIM_SELECTOR
8DKIM_FILE = CONFDIR/dkim/DKIM_DOMAIN-DKIM_SELECTOR.private.pem
9DKIM_PRIVATE_KEY = ${if exists{DKIM_FILE}{DKIM_FILE}{0}}
10.endif
Remember that the private key is supposed to be private, so make sure you set up the permissions
correctly: only the Exim-process (which runs as the Debian-exim
group on typical Debian installations)
needs access to it (and it only needs to read it), anybody else should be denied:
1# ls -lha /etc/exim4/dkim/
2total 16K
3drwxr-x--- 2 root Debian-exim 4.0K Oct 12 13:06 .
4-rw-r----- 1 root Debian-exim 1.7K Oct 12 12:39 umlaeute.mur.at-20221012.private.pem
Testing the setup
The obvious way to test the new setup is to just send an email via the mailserver.
It should now contain DKIM-Signature
header.
If the receiving SMTP-server runs SpamAssassin,
a few DKIM-related checks will be run,
and at least the DKIM_SIGNED
and DKIM_VALID
checks (and probably DKIM_VALID_AU
and DKIM_VALID_EF
as well)
should now succeed.