openDKIM and Postfix on Debian Server

May 9, 2018

Introduction

In this blog I will describe the linux configuration for DKIM which is a standard for signing email messages to ensure email clients like Gmail do not flag messages as SPAM.

I used the following articles to assist with setting up OpenDKIM on Debian. The most authoritative an well explained article on the setup is by Digital Ocean.

The most accurate example for my situation (using a subdomain such as mail.robobean.com) is on Ask Ubuntu.

I found this article useful terminal28.

I used a Google tool to test my DKIM DNS setup [toolbox.googleapps] (https://toolbox.googleapps.com/apps/checkmx/check?domain=mail.robobean.com&dkim_selector=mail “toolbox.googleapps”).

Install OpenDKIM

Pretty easy on Debian, just run apt-get install as root.

# apt-get install opendkim opendkim-tools
Where are all the Configuration files?

Now we will be working with some config files. Listed below are my files with the important configuration elements. These are the config changes I used in order to sign email messages from a subdomain mail.robobean.com. The key for the subdomain is to include the subdomain in the SigningTable file and ensure the subdomain is listed in the TrustedHosts file. Many examples do not show how to deal with subdomains such as mail.domain.com.

/etc/default/opendkim

# /etc/default$ cat opendkim
SOCKET=inet:12301@localhost
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

/etc/opendkim.conf (for a specific domain)

# /etc$ cat opendkim.conf
Domain                  robobean.com
KeyFile                 /etc/opendkim/keys/robobean.com/mail.private
Selector                mail
KeyTable                /etc/opendkim/KeyTable
SigningTable            /etc/opendkim/SigningTable
ExternalIgnoreList      /etc/opendkim/TrustedHosts
InternalHosts           /etc/opendkim/TrustedHosts
Mode                    sv
SubDomains              yes
Socket                  inet:12301@localhost
UserID                  opendkim:opendkim

/etc/opendkim.conf (for multiple domains on the same server leave out the domain-specific information)

# This is a basic configuration that can easily be adapted to suit a standard
# installation. For more advanced options, see opendkim.conf(5) and/or
# /usr/share/doc/opendkim/examples/opendkim.conf.sample.
#
#Domain                  example.com
#KeyFile                 /etc/opendkim/201205.private
#Selector                201205
#
# Commonly-used options
Canonicalization        relaxed/simple
Mode                    sv
SubDomains              yes
# Log to syslog
Syslog                  yes
LogWhy                  yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask                   022
UserID                  opendkim:opendkim
#
KeyTable                /etc/opendkim/KeyTable
SigningTable            /etc/opendkim/SigningTable
ExternalIgnoreList      /etc/opendkim/TrustedHosts
InternalHosts           /etc/opendkim/TrustedHosts
#
Socket                  inet:12301@localhost
#EOF

/etc/opendkim

/etc/opendkim$ ls -laF
drwxr-xr-x  3 opendkim opendkim 4096 May  8 11:34 ./
drwxr-xr-x 92 root     root     4096 May  9 15:13 ../
drwxr-xr-x  3 opendkim opendkim 4096 May  7 17:24 keys/
-rw-r--r--  1 opendkim opendkim   92 May  7 18:07 KeyTable
-rw-r--r--  1 opendkim opendkim   89 May  8 11:33 SigningTable
-rw-r--r--  1 opendkim opendkim   68 May  8 11:09 TrustedHosts

/etc/opendkim/keys/robobean.com$ ls
mail.private  mail.txt

/etc/postfix/main.cf

/etc/postfix$ cat main.cf
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

myhostname = mail.robobean.com

That is the landscape of configuration files! I will walk through each of these files.

Configuration

Create the opendkim directory to hold your keys and OpenDKIM configuration files

/etc$ mkdir -p /etc/opendkim/keys/domain.com
/etc/opendkim$ touch KeyTable
/etc/opendkim$ touch SigningTable
/etc/opendkim$ touch TrustedHosts

Generate the public and private keys used by postfix to sign emails. We will use the public key in the mail.txt file for our DNS setting. We always use the domain.com unless where indicated the subdomain is set.

The important command is opendkim-genkey where -s specifies the selector and -d the domain, this command will create two files, mail.private is our private key and mail.txt contains the public key. The selector mail is used throughout the configuration and is an easy way to refer to the key. Make sure to provide a different selector for each domain.

# cd /etc/opendkim/keys/domain.com
# opendkim-genkey -s mail -d domain.com
# chown opendkim:opendkim -R /etc/opendkim
# chmod 600 /etc/opendkim/keys/domain/mail.private

Now you can view the public key which will be used in the DNS settings.

/etc/opendkim/keys/domain.com# cat mail.txt
mail._domainkey IN      TXT     ( "v=DKIM1; h=sha256; k=rsa; "
          "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcivl2P6BPhcxgxRZgTbMuZfzdIIENlBsR0SWYhQeSc5T8Xg3HsIJe2+yp8U6JlaGDebAZIhscilVQ6V+xvcS/w7V3jbxHygexX+xzOGc33mzFEptkNLM904UC6878HyremIO0R4nXjNwYZmBPnlx2mk7SUjaEAWlkuCm9n99f6clOFBnCaLSjm7060rhW5YfySgQW8gEPXHNz"
          "Qc+/i3I4+DEYp4cZ3QjNlMkPiFAhoBLPjqoASZJ7HHp4TKd0vtWyPcjv0EGLFfNA2J32EtUczoB1F5jABSJT73BZIO74kzcnsweB6weMSA4keRFctYjKREhpz3vL196box0bgP6QIDAQAB" )  ; ----- DKIM key mail for robobean.com

It is important to realize that your DNS expects a TXT DNS Record which looks exactly like the following. There are many different user interfaces for setting DNS with your domain host, but what you ultimately need is a TXT record which looks like this. The domain should be mail._domainkey.mail.robobean.com and the content should be v=DKIM1; k=rsa; p=publickey

mail TXT 0 "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcivl2P6BPhcxgxRZgTbMuZfzdIIENlBsR0SWYhQeSc5T8Xg3HsIJe2+yp8U6JlaGDebAZIhscilVQ6V+xvcS/w7V3jbxHygexX+xzOGc33mzFEptkNLM904UC6878HyremIO0R4nXjNwYZmBPnlx2mk7SUjaEAWlkuCm9n99f6clOFBnCaLSjm7060rhW5YfySgQW8gEPXHNzQc+/i3I4+DEYp4cZ3QjNlMkPiFAhoBLPjqoASZJ7HHp4TKd0vtWyPcjv0EGLFfNA2J32EtUczoB1F5jABSJT73BZIO74kzcnsweB6weMSA4keRFctYjKREhpz3vL196box0bgP6QIDAQAB" 86400 0 0

Go to your DNS hosting website, add the TXT records. You can find out how your DNS record looks by running the dig command.

Note that you must create the subdomain mail._domainkey in the DNS. You need to be able to reach the exact subdomain address mail._domainkey.domain.com! I also added a TXT record for my subdomain mail._domainkey.mail.domain.com containing the same public key. I’m not sure if I needed to create both TXT records. If you don’t see a reply from the dig then make sure the subdomain is reachable.

The most difficult part of this exercise is that the DNS record has a time to live flag which requires you to wait for the changes to reflect. I set the TTL (time to live) to 480, but you may set it smaller.

# dig mail._domainkey.domain.com txt +short
"v=DKIM1\; k=rsa\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcivl2P6BPhcxgxRZgTbMuZfzdIIENlBsR0SWYhQeSc5T8Xg3HsIJe2+yp8U6JlaG" "DebAZIhscilVQ6V+xvcS/w7V3jbxHygexX+xzOGc33mzFEptkNLM904UC6878HyremIO0R4nXjNwYZmBPnlx2mk7SUjaEAWlkuCm9n99f6clOFBnCaLSjm7060rhW5Y" "fySgQW8gEPXHNzQc+/i3I4+DEYp4cZ3QjNlMkPiFAhoBLPjqoASZJ7HHp4TKd0vtWyPcjv0EGLFfNA2J32EtUczoB1F5jABSJT73BZIO74kzcnsweB6weMSA4keRFct" "YjKREhpz3vL196box0bgP6QIDAQAB"

At any point, you should also check that the private key is valid and working. Don’t worry about the key not secure warning.

# opendkim-testkey -d domain.com -s mail -k /etc/opendkim/keys/domain.com/mail.private -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/opendkim/keys/domain.com/mail.private
opendkim-testkey: checking key 'mail._domainkey.domain.com'
opendkim-testkey: key not secure
opendkim-testkey: key OK

Now that you have a reachable public key as a TXT record in the DNS, you can continue with the configuration of OpenDKIM.

Create the files KeyTable, SigningTable and TrustedHosts

/etc/opendkim$ ls -laF
drwxr-xr-x  3 opendkim opendkim 4096 May  8 11:34 ./
drwxr-xr-x 92 root     root     4096 May  9 15:13 ../
drwxr-xr-x  3 opendkim opendkim 4096 May  7 17:24 keys/
-rw-r--r--  1 opendkim opendkim   92 May  7 18:07 KeyTable
-rw-r--r--  1 opendkim opendkim   89 May  8 11:33 SigningTable
-rw-r--r--  1 opendkim opendkim   68 May  8 11:09 TrustedHosts

In KeyTable file, provide the location of you private key.

/etc/opendkim# cat KeyTable
mail._domainkey.domain.com domain.com:mail:/etc/opendkim/keys/domain.com/mail.private

In the SigningTable file, make two records. One for the domain and the other for the mail subdomain. In my case, the subdomain is pointing to my mail server

/etc/opendkim# cat SigningTable
domain.com mail._domainkey.domain.com
mail.domain.com mail._domainkey.domain.com

In the TrustedHosts file, ensure that both domain and subdomains are listed

/etc/opendkim# cat TrustedHosts
127.0.0.1
localhost
mail.domain.com
domain.com

209.135.132.41

Finally, Ensure the settings for the following configuration files. Scroll up to see how they should look. Complete the configuration of /etc/postfix/main.cf.

/etc/default/opendkim

/etc/opendkim.conf

/etc/postfix/main.cf

After making any changes to files, you must ensure the permissions are set correctly with the commands

# chown opendkim:opendkim -R /etc/opendkim
# chmod 600 /etc/opendkim/keys/domain/mail.private

After any change, we must restart the postfix and opendkim services. Use systemctl or service commands.

systemctl restart opendkim

# service postfix restart
# service opendkim restart
Testing

I used a Google tool to test my DKIM DNS setup [toolbox.googleapps] (https://toolbox.googleapps.com/apps/checkmx/check?domain=mail.robobean.com&dkim_selector=mail “toolbox.googleapps”). I found the tool to be most responsive to changes in the DNS settings.

Another great testing tool is an email which replies with a report [https://port25.com/authentication-checker/] (https://port25.com/authentication-checker/https://port25.com/authentication-checker/").

Conclusion

It is frustrating to figure out the DNS settings, but once a dig test is successful, then you are over the difficult part.


comments powered by Disqus