Setting up DKIM for a domain with OpenDKIM and DNS
One of the critical components of hosting a mail server and ensuring that your emails get delivered to inboxes is DKIM. DomainKeys Identified Mail is an email authentication protocol that allows receiving mail servers to verify that the email message truly came from the domain that it claims to have arrived from.
DKIM uses public-key cryptography to enable senders to sign emails, and together with DNS, recipients can verify the signatures.
If you already have OpenDKIM configured and running, adding a new domain is fairly straight forward.
First, you will need to generate a key pair with opendkim-genkey
. To keep things organized, I like to store keys in their own directories under /etc/opendkim/keys
. Create a new directory for newdomain.com
there before generating the keys. The new directory and files should be owned by opendkim:opendkim
.
Since a domain can have multiple DKIM signatures you need to supply a selector name with the -s
argument. We will use mail
as the selector in this example.
These commands should be executed as the root user, or prefixed with sudo
.
mkdir /etc/opendkim/keys/newdomain.com
opendkim-genkey -b 1024 -d newdomain.com -D /etc/opendkim/keys/newdomain.com -s mail -v
chown opendkim:opendkim /etc/opendkim/keys -R
You should now have both a private key and public key generated, named mail.private
and mail.txt
respectively, in the /etc/opendkim/keys/newdomain.com
directory. The public key in the text file is stored in the form of a DNS record, so we will need to extract the specific value in a later step.
ls -la /etc/opendkim/keys/newdomain.com/
total 16
drwxr-xr-x 2 opendkim opendkim 4096 Feb 20 22:15 .
drwx------ 3 opendkim opendkim 4096 Feb 20 22:15 ..
-rw------- 1 opendkim opendkim 887 Feb 20 22:15 mail.private
-rw------- 1 opendkim opendkim 320 Feb 20 22:15 mail.txt
Now that we have our keys ready we will need to update our /etc/opendkim.conf
configuration file with our new domain, by adding the following Domain
line at the bottom of the file.
Domain newdomain.com
Next, we will need to add configuration lines for the new domain to the KeyTable
, SigningTable
and InternalHosts
files. The paths to these files are defined in the opendkim.conf
file.
The KeyTable
file needs to know about the new domain, selector and path to the private key. If you have decided to use a different selector, replace occurrences of mail
with your selector below.
mail._domainkey.newdomain.com newdomain.com:mail:/etc/opendkim/keys/newdomain.com/mail.private
The SigningTable
is used to configure which private key will be used for which domain and email address. Add the following line to use the same private key for all email addresses under newdomain.com
.
*@newdomain.com mail._domainkey.newdomain.com
And lastly, we will add the new domain to the InternalHosts
file, which is also referred to as the trusted hosts file. Add the following line at the bottom of the file.
*.newdomain.com
We can now restart the opendkim
and postfix
services so our changes take effect.
systemctl restart opendkim
systemctl restart postfix
The final piece of the setup is to publish the public key as a new TXT type DNS record for newdomain.com
. You will need to do this at your domain name registar, or whereever the DNS for the domain is configured.
cat keys/newdomain.com/mail.txt
mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeJDREunvEr2s5StKbNYIDuXVqGHC75BA/Lz6MCqDp9ByeOLEJzVRBMQxv09QGrjnik1oiimOaLVQHYP7tzF+g6iqAhOo8Ja0UDMbZZunV7M8ixKtj5PDKl4E9oCmaH7MCEZqyxaPFC4Y3nrE7U8KIAQ27VjWBp5LqkxFFSsDAUQIDAQAB" ) ; ----- DKIM key mail for newdomain.com
The first part mail._domainkey
should be used as the Name
of the TXT record, and the quoted part starting with v=DKIM1
should be used as the Value
for the record. Be sure to not include any quotation marks. The public key is base64 encoded and contained after the p=
part. Save the record and we should be all set once DNS changes propagate.
v=DKIM1; h=sha256; k=rsa;
p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeJDREunvEr2s5StKbNYIDuXVqGHC75BA/Lz6MCqDp9ByeOLEJzVRBMQxv09QGrjnik1oiimOaLVQHYP7tzF+g6iqAhOo8Ja0UDMbZZunV7M8ixKtj5PDKl4E9oCmaH7MCEZqyxaPFC4Y3nrE7U8KIAQ27VjWBp5LqkxFFSsDAUQIDAQAB
To verify if our DNS record is being served correctly we can use dig
to check the TXT record by prefixing the domain name with our TXT record name and specifying that we are after a txt
record.
dig mail._domainkey.newdomain.com txt
We should see the contents of our created TXT record in the answer section like shown below.
;; ANSWER SECTION:
mail._domainkey.newdomain.com. 3000 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeJDREunvEr2s5StKbNYIDuXVqGHC75BA/Lz6MCqDp9ByeOLEJzVRBMQxv09QGrjnik1oiimOaLVQHYP7tzF+g6iqAhOo8Ja0UDMbZZunV7M8ixKtj5PDKl4E9oCmaH7MCEZqyxaPFC4Y3nrE7U8KIAQ27VjWBp5LqkxFFSsDAUQIDAQAB"
Now that we have everything configured it is time to test our DKIM-Signature
email header injection. You can use a free tool such as https://www.mail-tester.com/ that provides an email address to send a test email to and will verify your DKIM signature. You can also send an email to a gmail address and if everything is working you should see a Signed by
data row in the email message dropdown beside to me
, or view the original message and check if your DKIM-Signature
is included in the email headers.
You can check your mail.log
file for any opendkim
lines to troubleshoot any issues. Generally only errors or warnings will appear, but if you’d like to see successful signature header insertion log lines you will need to add SyslogSuccess yes
to /etc/opendkim.conf
.
Feb 21 17:17:17 mail opendkim[29094]: 04892BC163: DKIM-Signature field added (s=mail, d=newdomain.com)