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.
Links
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.