Skip to content

DKIM

What is DKIM?

From Wikipedia:

DomainKeys Identified Mail (DKIM) is an email authentication method designed to detect forged sender addresses in emails (email spoofing), a technique often used in phishing and email spam.

DKIM allows the receiver to check that an email claimed to have come from a specific domain was indeed authorized by the owner of that domain. It achieves this by affixing a digital signature, linked to a domain name, to each outgoing email message. The recipient system can verify this by looking up the sender's public key published in the DNS. A valid signature also guarantees that some parts of the email (possibly including attachments) have not been modified since the signature was affixed. Usually, DKIM signatures are not visible to end-users, and are affixed or verified by the infrastructure rather than the message's authors and recipients.

Installing and Configuring DKIM

First ensure you're in a sudo shell and install OpenDKIM which is an open source implementation of the DKIM sender authentication system:

apt update && sudo apt install opendkim opendkim-tools

Enable the service:

systemctl enable opendkim

Then add the postfix user to the opendkim group:

gpasswd -a postfix opendkim

Edit the OpenDKIM main configuration file:

nano /etc/opendkim.conf

Uncomment or add lines as below:

Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no

UMask                   007

AutoRestart             yes
AutoRestartRate         10/1M
Background              yes
DNSTimeout              5
SignatureAlgorithm      rsa-sha256

#OpenDKIM user
# Remember to add user postfix to group opendkim
UserID                  opendkim

# Map domains in From addresses to keys used to sign messages
KeyTable                refile:/etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table

# Hosts to ignore when verifying signatures
ExternalIgnoreList      /etc/opendkim/trusted.hosts
InternalHosts           /etc/opendkim/trusted.hosts

Now we create a directory structure for OpenDKIM:

mkdir /etc/opendkim
mkdir /etc/opendkim/keys

Change the owner from root to opendkim and make sure only the opendkim user can read and write to the keys directory:

chown -R opendkim:opendkim /etc/opendkim
chmod go-rw /etc/opendkim/keys

Create the signing table:

nano /etc/opendkim/signing.table

Add this line to the file. Note that your-domain.com and your-domain is different. The latter should not contain the top-level domain. If you have more than one domain, use one line per domain entry.

*@example.com default._domainkey.example.com

Then create the key table:

nano /etc/opendkim/key.table

Add the following line - or multiple lines for multiple domains:

default._domainkey.example.com    example.com:default:/etc/opendkim/keys/example.com/default.private

Save and close the file.

Create the trusted hosts file:

nano /etc/opendkim/trusted.hosts

Add the following lines to the newly created file:

127.0.0.1
localhost

hostname
example.com
*.example.com

The above means that messages coming from the above IP addresses and domains will be trusted and signed.

Generating the DKIM keys

Since DKIM is used to sign outgoing messages and verify incoming messages, we need to generate a private key for signing and a public key for remote verifier. The public key will be published in DNS.

Create a separate folder for the domain:

mkdir /etc/opendkim/keys/example.com

Generate keys using the opendkim-genkey tool:

opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s default -v

The above command will create 2048 bits keys. -d (domain) specifies the domain. -D (directory) specifies the directory where the keys will be stored and we use default as the selector (-s), also known as the name. Once the command is executed, the private key will be default.private and default.txt will be the TXT record that contains public key.

Make opendkim as the owner of the private key:

chown opendkim:opendkim /etc/opendkim/keys/example.com/default.private

Display the public key:

cat /etc/opendkim/keys/example.com/default.txt

The string after the p parameter is the public key.

In your DNS manager, create a TXT record, enter default._domainkey in the name field. Then copy everything in the parentheses and paste it into the value field. Delete all double quotes and white spaces. If you don’t delete them, then the key test in the next step will fail.

Enter the following command to test your key:

opendkim-testkey -d example.com -s default -vvv

If everything is OK, you will see

key OK

It may also say key not secure. If so then it doesn't mean there's an error. It is an expected consequence of not using DNSSSEC. DNSSEC can be setup by following the instructions on the Cloudflare DNS management page if you require it (and are using Cloudflare to manage DNS!).

Postfix can talk to OpenDKIM via a Unix socket file. The default socket file used by OpenDKIM is at /var/run/opendkim/opendkim.sock. But the postfix SMTP daemon shipped with Ubuntu runs in a chroot jail, which means that the SMTP daemon resolves all filenames relative to the Postfix queue directory (/var/spool/postfix). So we need to change the socket file.

Create a directory to hold the OpenDKIM socket file and only allow opendkim user and postfix group to access it:

mkdir /var/spool/postfix/opendkim
chown opendkim:postfix /var/spool/postfix/opendkim

Then edit the socket configuration file:

nano /etc/default/opendkim

Find the following line:

SOCKET="local:/run/opendkim/opendkim.sock"

Replace it with:

SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"

Save and close the file.

Now check the /etc/default/opendkim file:

nano /etc/default/opendkim

If you can find the following line:

SOCKET="local:/run/opendkim/opendkim.sock"

or

SOCKET=local:$RUNDIR/opendkim.sock

Then change it to

SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"

Configuring Postfix

Next, we need to edit Postfix main configuration file:

nano /etc/postfix/main.cf

Add the following lines after smtpd_recipient_restriction section:

# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

Save and close the file. Then restart opendkim and postfix service:

systemctl restart opendkim postfix

Testing

To test SPF and DKIM, send a test email from one of your new addresses to check-auth@verifier.port25.com and wait for the reply. It can sometimes be an issue sending emails to an outlook.com address as Microsoft use their own internal blacklist that incorrectly blocks many legitimate IP addresses. If you have this issue, try completing the form at https://support.microsoft.com/en-us/getsupport?oaspworkflow=start_1.0.0.0&wfname=capsub&productkey=edfsmsbl3&locale=en-us&ccsid=635714983457075069 or alternatively going through the process here: https://sendersupport.olc.protection.outlook.com/snds/

Testing Email Score and Placement

You can also go to https://www.mail-tester.com. You will see a unique email address. Send an email from your domain to this address and then check your score. As you can see, I got a perfect score. Mail-tester.com can only show you a sender score. There’s another service called GlockApps that allow you to check if your email is placed in the recipient’s inbox or spam folder, or rejected outright. It supports many popular email providers like Gmail, Outlook, Hotmail, YahooMail, iCloud mail, etc

Further Reading:

https://www.emailonacid.com/blog/article/email-development/what_is_dkim_everything_you_need_to_know_about_digital_signatures/
https://wiki.archlinux.org/index.php/OpenDKIM