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)

Resources