Install and Configure OpenDKIM on CentOS 8/RHEL 8 Mail Server

Previously I showed you how to set up SPF and DKIM on CentOS/RHEL mail server. Two common pieces of software that can do DKIM signing and verification on Linux are OpenDKIM and Amavis. In that tutorial I used Amavis, because at the time OpenDKIM isn’t included in any CentOS 8/RHEL 8 repository. As of now, OpenDKIM is included in the EPEL repository. Some folks prefer to use OpenDKIM so I will show you how in this tutorial.

What is DKIM?

DKIM (DomainKeys Identified Mail) is a type of TXT records in DNS that can help with preventing email spoofing and making legitimate emails delivered into the recipient’s inbox instead of spam folder. DKIM uses a private key to add a signature to emails sent from your domain. Receiving SMTP servers verify the signature by using the corresponding public key, which is published in your domain’s DNS records.

Disabling DKIM in Amavis

If you followed my previous Amavis tutorial, but now you want to use OpenDKIM, you need to disable DKIM in Amavis. Edit the main configuration file.

sudo nano /etc/amavisd/amavisd.conf

Find the following lines.

$enable_dkim_verification = 1;  # enable DKIM signatures verification
$enable_dkim_signing = 1;       # load DKIM signing code, keys defined by dkim_key

Add a # character at the beginning of each line to comment them out.

#$enable_dkim_verification = 1;  # enable DKIM signatures verification
#$enable_dkim_signing = 1;       # load DKIM signing code, keys defined by dkim_key

Save and close the file. Then restart Amavis.

sudo systemctl restart amavisd

Step 1: Install and Configure OpenDKIM on CentOS 8/RHEL8

First enable the EPEL (Extra Packages for Enterprise Linux) repository and install OpenDKIM.

sudo dnf install epel-release

sudo dnf install opendkim opendkim-tools

Edit OpenDKIM main configuration file.

sudo nano /etc/opendkim.conf

Find the following line.

Mode     v

By default, OpenDKIM runs in verification mode (v), which will verify the DKIM signature of incoming email messages. We need to sign outgoing emails, so change this line to the following to enable signing mode.

Mode           sv

Then find the following lines.

## Specifies whether or not the filter should generate report mail back
## to senders when verification fails and an address for such a purpose
## is provided. See opendkim.conf(5) for details.
SendReports yes

## Specifies the sending address to be used on From: headers of outgoing
## failure reports. By default, the e-mail address of the user executing
## the filter is used (executing_user@hostname).
# ReportAddress "Example.com Postmaster" <[email protected]>

When a signature verification fails and the signature included a reporting request (“r=y”) and the signing domain advertises a reporting address (i.e. ra=user) in a reporting record in the DNS, OpenDKIM will send a structured report to that address containing details needed to reproduce the problem. You may want to use a particular From email address to send the report. Uncomment the ReportAddress parameter and change email address. Note that this will not create the backscatter problem, because report emails will sent to an email address specified in the sender domain’s DNS record.

Find the following line and comment it out, because we will use separate keys for each domain name.

KeyFile   /etc/opendkim/keys/default.private

Next, find the following 4 lines and uncomment them.

# KeyTable            /etc/opendkim/KeyTable

# SigningTable        refile:/etc/opendkim/SigningTable

# ExternalIgnoreList  refile:/etc/opendkim/TrustedHosts

# InternalHosts       refile:/etc/opendkim/TrustedHosts

Save and close the file.

Step 2: Create Signing Table, Key Table and Trusted Hosts File

Edit the signing table file.

sudo nano /etc/opendkim/SigningTable

Add the following line at the end of this file. This tells OpenDKIM that if a sender on your server is using a @your-domain.com address, then it should be signed with the private key identified by 20200308._domainkey.your-domain.com.

*@your-domain.com    20200308._domainkey.your-domain.com

20200308 is the DKIM selector. A domain name might have multiple DKIM keys. The DKIM selector allows you to choose a particular DKIM key. You can use whatever name for the DKIM selector, but I found it’s convienent to use the current date (March 8, 2020) as the DKIM selector. Save and close the file. Then edit the key table file.

sudo nano /etc/opendkim/KeyTable

Add the following line, which specifies the location of the DKIM private key.

20200308._domainkey.your-domain.com     your-domain.com:20200308:/etc/opendkim/keys/your-domain.com/20200308.private

Save and close the file. Next, edit the trusted hosts file.

sudo nano /etc/opendkim/TrustedHosts

127.0.0.0.1 and ::1 are included in this file by default. Now add the following line. This tells OpenDKIM that if an email is coming from your own domain name, then OpenDKIM should sign the email but don’t perform DKIM verification on the email.

.your-domain.com

Save and close the file.

Note: You should not add an asterisk in the domain name like this: *.your-domain.com. There should be only a dot before the domain name.

Step 3: Generate Private/Public Keypair

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. Public key will be published in DNS.

Create a separate folder for the domain.

sudo mkdir /etc/opendkim/keys/your-domain.com

Generate keys using opendkim-genkey tool.

sudo opendkim-genkey -b 2048 -d your-domain.com -D /etc/opendkim/keys/your-domain.com -s 20200308 -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. I use 20200308 as the DKIM selector. Once the command is executed, the private key will be written to 20200308.private file and the public key will be written to 20200308.txt file.

centos 8 opendkim

By default, only root can read and write to the key files. Make opendkim as the owner of the private key.

sudo chown opendkim:opendkim /etc/opendkim/keys/ -R

Step 4: Publish Your Public Key in DNS Records

Display the public key

sudo cat /etc/opendkim/keys/your-domain.com/20200308.txt

The string after the p parameter is the public key.

install opendkim centos 8

In you DNS manager, create a TXT record, enter 20200308._domainkey in the name field. (You need to replace 20200308 with your own DKIM selector.) Then go back to the terminal window, copy everything in the parentheses and paste it into the value field of the DNS record. You need to delete all double quotes and line breaks in the value field. If you don’t delete them, then key test in the next step will probably fail.

DKIM records

Step 5: Test DKIM Key

Enter the following command on your CentOS 8/RHEL 8 server to test your key.

sudo opendkim-testkey -d your-domain.com -s 20200308 -vvv

If everything is OK, you will see the key OK message.

opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key '20200308._domainkey.linuxbabe.com'
opendkim-testkey: key OK

Note that your DKIM record may need sometime to propagate to the Internet. Depending on the domain registrar you use, your DNS record might be propagated instantly, or it might take up to 24 hours to propagate. You can go to https://www.dmarcanalyzer.com/dkim/dkim-check/, enter 20200308 as the selector and enter your domain name to check DKIM record propagation.

If you see “Key not secure”, don’t panic. This is because DNSSEC isn’t enabled on your domain name. DNSSEC is a security standard for secure DNS query. Most domain names haven’t enabled DNSSEC. You can continue to follow this guide.

Now we can start the opendkim service.

sudo systemctl start opendkim

And enable auto-start at boot time.

sudo systemctl enable opendkim

OpenDKIM listens on 127.0.0.1:8891.

Step 6: Connect Postfix to OpenDKIM

Edit Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following lines at the end of this file, so Postfix will be able to call OpenDKIM via the milter protocol. Note that you should use 127.0.0.1 as the address. Don’t use localhost.

# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters

Save and close the file. Then add postfix user to opendkim group.

sudo gpasswd -a postfix opendkim

Restart postfix service.

sudo systemctl restart postfix

Step 7: SPF and DKIM Check

Now you can use your desktop email client or webmail client to send a test email to [email protected] and get a free email authentication report. Here’s the report I got from port25.com.

postfix-spf-dkim-centos8-rhel8

You can also send a test email from your mail server to your Gmail account to see if SPF and DKIM checks are passed. On the right side of an opened email message in Gmail, if you click the show original button from the drop-down menu, you can see the authentication results.

Gmail SPF and DKIM check scalahosting

If your message is not signed and DKIM check failed, you may want to check postfix log (/var/log/maillog) to see what’s wrong in your configuration.

Your email server will also perform DKIM verification on incoming emails. You can see the results in the email headers. The following is SPF and DKIM check on a sender using Gmail.

Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::c2d; helo=mail-yw1-xc2d.google.com; [email protected]; receiver=<UNKNOWN> 
Authentication-Results: email.linuxbabe.com;
	dkim=pass (2048-bit key; unprotected) header.d=gmail.com [email protected] header.b="XWMRd2co";
	dkim-atps=neutral

How to Configure OpenDKIM For Multiple Domains

I have written a guide to hosting multiple domains on CentOS 8/RHEL 8 mail server with PostfixAdmin. In that article, I used Amavis for DKIM signing and verification. I you use OpenDKIM, then you need to skip step 3 in that article.

To configure OpenDKIM for multiple domains, you need to add the other domains in the signing table, key table and trusted hosts file like below.

Signing table:

*@domain1.com       20200308._domainkey.domain1.com
*@domain2.com       20200308._domainkey.domain2.com

Key table:

20200308._domainkey.domain1.com     domain1.com:20200308:/etc/opendkim/keys/domain1.com/20200308.private
20200308._domainkey.domain2.com     domain2.com:20200308:/etc/opendkim/keys/domain2.com/20200308.private

Trusted hosts:

127.0.0.1
localhost

.domain1.com
.domain2.com

Then generate the DKIM Private/Public keypair and add the DKIM public key in DNS as mentioned in step 3, step 4 and step 5 for other domains. Restart OpenDKIM and you are done.

sudo systemctl restart opendkim

Configuration Error in Email Client

DKIM signing could fail if you don’t use the correct SMTP/IMAP settings in your email client.

Correct Settings:

  • SMTP protocol: enter mail.your-domain.com as the server name, choose port 587 and STARTTLS. Choose normal password as the authentication method.
  • IMAP protocol: enter mail.your-domain.com as the server name, choose port 143 and STARTTLS. Choose normal password as the authentication method.

or

  • SMTP protocol: enter mail.your-domain.com as the server name, choose port 465 and SSL/TLS. Choose normal password as the authentication method.
  • IMAP protocol: enter mail.your-domain.com as the server name, choose port 993 and SSL/TLS. Choose normal password as the authentication method.

Wrong Settings:

  • Use port 25 as the SMTP port in mail clients to submit outgoing emails.
  • No encryption method was selected.

Port 25 should be used for SMTP server to SMTP server communication. Please don’t use it in your email client to submit outgoing emails.

You should select an encryption method (STARTTLS or SSL/TLS) in your email client.

Next Step

I hope this tutorial helped you install and configure OpenDKIM on CentOS 8/RHEL 8 mail server. Now you may want to read the following tutorial to set up OpenDMARC to block email spoofing.

As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 4 Average: 5]

17 Responses to “Install and Configure OpenDKIM on CentOS 8/RHEL 8 Mail Server

  • Thank you !

    Your tutorials are pure gold.

  • Thanks for the tutorials, they are clear and well written!

    I followed all the steps thus far and everything is working as expecting, however there is a problem with the connection between Postfix and OpendKim.
    When checking the logs I see the following:

    warning: connect to Milter service inet:127.0.0.1:8891: Connection timed out

    Therefore, the DKIM signature is not coming through with my emails.
    When sending an email through PostfixAdmin it also takes a while because it is timing out I suppose.

    I hope you have a clue what it might be. (I checked the internet and tried many things but I can’t seem to find an answer)

    Please note, I run Centos 7.

    • Well, after a good night of sleep and some coffee I finally tackled the problem this morning.
      I was my own fault because I set up iptables configuration to strict and therefore not allowing any internal traffic.

      Added following rules and it works:

       iptables -A INPUT -i lo -j ACCEPT 
       iptables -A OUTPUT -o lo -j ACCEPT 
  • I note I always get the same private and public strings as you do in the example when I run opendkim-genkey. How do I seed it differently?

    • Ah dumb question – it just looks he same near the beginning and the end.

  • Hello, at step 5 when i execute the opendkim-testkey command i receive: key 20200527._domainkey.localdomain.com: invalid key version ‘spf1-all’. Why? Can’t find any thread about that.

    • Xiao Guoan (Admin)
      4 years ago

      It seems you put your SPF record into the DKIM record.

  • This doesn’t seem to be a valid RSA public key: RSA.xs:178: OpenSSL error: bad base64 decode at blib/lib/Crypt/OpenSSL/RSA.pm (autosplit into blib/lib/auto/Crypt/OpenSSL/RSA/new_public_key.al) line 91.

  • Thanks man, it work for me ^_^

  • Hi,

    Thanks for putting together these tutorials, they have been of immense help over the years.

    I used most of your CentOS 8 postfix setup, including spf, dmarc, and dkim. This was over a year ago and things have been running fine since. One of my users contacted me recently saying they couldn’t send email. It was a case of it working on the Friday to not working on the Monday morning. No manual changes, deletions or additions had been made on the mail server, there were automated updates that installed over that weekend but none that obviously related to the problem. All other domains continued working just fine.

    A check in the logs showed (the only change made is substituting the domain name with ‘example’ and the content of the keys):

    opendkim[4427]: 32D4E754C1: signing table references unknown key 2022012001._domainkey.example.co.uk

    Dig from the mail server worked:

    dig 2022012001._domainkey.example.co.uk txt +short 
    "v=DKIM1; k=rsa; " "first part of key" "remains of key" 

    The key test worked:

    udo -u postfix opendkim-testkey -d example.co.uk -s 2022012001 -vvv 
    opendkim-testkey: using default configfile /etc/opendkim.conf 
    opendkim-testkey: checking key '2022012001._domainkey.example.co.uk' 
    opendkim-testkey: key not secure 
    opendkim-testkey: key OK

    I removed the /etc/opendkim/keys/example.co.uk directory and contents.

    Shutdown, halted and restarted the server

    Recreated the directory

    mkdir /etc/opendkim/keys/example.co.uk
    chown opendkim:opendkim /etc/opendkim/keys/ -R

    I switched out the key using:

    sudo -u opendkim opendkim-genkey -b 2048 -d example.co.uk -D /etc/opendkim/keys/example.co.uk -s default-v

    Made the necessary changes in SigningTable:

    *@example.co.uk default._domainkey.example.co.uk

    and to the KeyTable:

    default._domainkey.example.co.uk:default:/etc/opendkim/keys/example.co.uk/default.private

    The key test worked:

    sudo -u postfix opendkim-testkey -d example.co.uk -s default -vvv 
    opendkim-testkey: using default configfile /etc/opendkim.conf 
    opendkim-testkey: checking key 'default._domainkey.example.co.uk' 
    opendkim-testkey: key not secure 
    opendkim-testkey: key OK

    Dig from the mail server worked:

    dig default._domainkey.example.co.uk txt +short 
    "v=DKIM1; k=rsa; " "first part of key" "remains of key" 

    After rebooting it continues with the original error:

    opendkim[1041]: 2C6DB754C1: signing table references unknown key default._domainkey.example.co.uk

    I have double checked paths and permissions.
    I have several other domains in the same mail server, configured identically, none of which exhibit this behaviour, even after I update their keys.
    I have tried doing the test with opendkim and postfix as the user with the same (correct) results
    I have tried reducing the dns ttl to 10 minutes. I’m pretty sure DNS itself is not the issue, but I’m aware caching can be an issue, hence dropping the ttl (which apparently did nothing) after the original ttl expired.

    I’m hoping you might have some suggestions, I’m stumped.

    Kind regards and many thanks

    Nigel.

  • chuyenim
    2 years ago

    I have installed opendkim but when i run the following command, it show an error:

    sudo opendkim-genkey -b 2048 -d domain.xyz -D /etc/opendkim/keys/domain.xyz -s 20200308 -v
    sudo: opendkim-genkey: command not found

    Any ideas?

  • sudo dnf install opendkim-tools

  • Problem:
    In you DNS manager, create a TXT record, enter 20200308._domainkey in the name field.

    Test DKIM Key

    sudo opendkim-testkey -d your-domain.com -s 20200308 -vvv
    
    opendkim-testkey: using default configfile /etc/opendkim.conf
    opendkim-testkey: checking key '20200308._domainkey.your-domain.com'
    opendkim-testkey: '20200308._domainkey.your-domain.com' query failed

    So, it looks like you need to append your domain name to the TXT record name

  • kuruoshi
    1 year ago

    This helps me with err about opendkim not signing mails.

    https://serverfault.com/a/861701

  • Thanks a lot! I had to add this to my /etc/opendkim.conf because it just refused to listen on port 8891. Other than this, I followed the guide to a tee and it went flawlessly.

    Socket inet:[email protected]

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here