Introduction

Email deliverability is one of the major challenges when setting up a new mail server. Emails sent from an untrusted or unauthenticated mail server may be delivered to spam folders or rejected by popular email providers.

DomainKeys Identified Mail (DKIM) is an email authentication mechanism that allows an outgoing mail server to digitally sign emails. The receiving mail server can use the public key published in the sender’s DNS records to verify that the email was authorized by the sending domain and that the signed message has not been modified during transmission.

In this guide, we will configure OpenDKIM as the DKIM signing service and integrate it with Postfix. OpenDKIM will digitally sign outgoing emails, while Postfix will pass the messages to OpenDKIM through a Milter interface.

The guide covers:

  • Installing OpenDKIM
  • Configuring OpenDKIM
  • Generating DKIM keys
  • Configuring KeyTable and SigningTable
  • Configuring trusted hosts
  • Publishing the DKIM public key in DNS
  • Integrating OpenDKIM with Postfix
  • Starting and enabling the services
  • Verifying DKIM signatures

Prerequisites

Before starting the configuration, ensure the following requirements are available.

1. CentOS Server

A CentOS 6 or CentOS 7 server with root or sudo access.

2. Postfix

Postfix must already be installed and configured as the mail transfer agent.

Verify the installation:

postconf mail_version

Check the Postfix service:

service postfix status

3. Domain Name

You should have a valid domain that will be used to send emails.

For this example, we will use:

domain.tld

Replace domain.tld with your actual domain throughout the configuration.

4. DNS Access

You must have access to the DNS management panel for the domain because the DKIM public key needs to be published as a TXT record.

5. EPEL Repository

The EPEL repository should be enabled because OpenDKIM can be installed from EPEL on CentOS 6/7.

6. SMTP Connectivity

The server should have working outbound SMTP connectivity and Postfix should already be able to send emails.


Technical Implementation

Step 1: Install the EPEL Repository

First, enable the EPEL repository.

CentOS 6

wget http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm

CentOS 7

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm

Alternatively:

yum install epel-release

Verify the repository:

yum repolist

Step 2: Install OpenDKIM

Install OpenDKIM and its required packages:

yum install opendkim

Verify that OpenDKIM was installed:

rpm -qa | grep opendkim

Check the installed binary:

which opendkim

Step 3: Configure OpenDKIM

Back up the existing configuration before making changes:

cp /etc/opendkim.conf /etc/opendkim.conf.bak

Open the configuration file:

vi /etc/opendkim.conf

Configure the required parameters:

AutoRestart              Yes
AutoRestartRate          10/1h
LogWhy                   Yes
Syslog                   Yes
SyslogSuccess            Yes
Mode                     sv
Canonicalization         relaxed/simple
ExternalIgnoreList       refile:/etc/opendkim/TrustedHosts
InternalHosts            refile:/etc/opendkim/TrustedHosts
KeyTable                 refile:/etc/opendkim/KeyTable
SigningTable             refile:/etc/opendkim/SigningTable
SignatureAlgorithm       rsa-sha256
Socket                   inet:8892@localhost
PidFile                  /var/run/opendkim/opendkim.pid
UMask                    022
UserID                   opendkim:opendkim
TemporaryDirectory       /var/tmp

The important configuration files used by OpenDKIM are:

/etc/opendkim.conf
/etc/opendkim/KeyTable
/etc/opendkim/SigningTable
/etc/opendkim/TrustedHosts

The Milter socket is configured to listen on:

127.0.0.1:8892

Step 4: Generate DKIM Keys

Create a directory for the domain:

mkdir -p /etc/opendkim/keys/domain.tld

Generate the DKIM key pair:

opendkim-genkey -D /etc/opendkim/keys/domain.tld/ -d domain.tld -s default

This will generate two files:

default.private
default.txt

The files contain:

  • default.private — Private DKIM key used by OpenDKIM to sign emails.
  • default.txt — Public DKIM key that must be published in DNS.

Set the appropriate ownership:

chown -R opendkim:opendkim /etc/opendkim/keys/domain.tld

Rename the private key to match the configuration:

mv /etc/opendkim/keys/domain.tld/default.private \
   /etc/opendkim/keys/domain.tld/default

Set secure permissions on the private key:

chmod 600 /etc/opendkim/keys/domain.tld/default

Verify:

ls -l /etc/opendkim/keys/domain.tld/

Step 5: Configure KeyTable

Open the KeyTable:

vi /etc/opendkim/KeyTable

Add:

default._domainkey.domain.tld domain.tld:default:/etc/opendkim/keys/domain.tld/default

The configuration follows this format:

key_name domain:selector:key_file

Here:

  • domain.tld is the sending domain.
  • default is the DKIM selector.
  • /etc/opendkim/keys/domain.tld/default is the private key.

Step 6: Configure SigningTable

Open:

vi /etc/opendkim/SigningTable

Add:

*@domain.tld default._domainkey.domain.tld

The * means that emails sent from any address belonging to domain.tld will use the configured DKIM key.

For example:

admin@domain.tld
support@domain.tld
sales@domain.tld

will all be signed using:

default._domainkey.domain.tld

Step 7: Configure TrustedHosts

Open:

vi /etc/opendkim/TrustedHosts

Add the mail server’s trusted hosts.

For example:

127.0.0.1
localhost
domain.tld

If required, the server’s IP address can also be included:

192.0.2.10

Do not add arbitrary external IP addresses to this file. Only trusted systems that are authorized to submit mail through the DKIM signer should be included.


Step 8: Configure DNS DKIM Record

The public DKIM key generated earlier can be viewed with:

cat /etc/opendkim/keys/domain.tld/default.txt

You will see a record similar to:

default._domainkey IN TXT (
"v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
)

Create a DNS TXT record for:

default._domainkey.domain.tld

with the generated public key as the value.

For example:

Type: TXT
Name: default._domainkey
Value: v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBg...

Do not copy the example key above. Always use the public key generated on your own server.

Important

The private key must never be published in DNS.

Only the public key from default.txt should be added to DNS.

DNS propagation time depends on the DNS provider and TTL. It may become available quickly, but cached records can take longer to update.


Step 9: Verify the DNS Record

After adding the DNS record, verify it using:

host -t txt default._domainkey.domain.tld

You can also use:

dig TXT default._domainkey.domain.tld

For a shorter output:

dig TXT default._domainkey.domain.tld +short

The response should contain something similar to:

"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBg..."

If the TXT record is not returned, verify the DNS record name, value, and DNS provider configuration.


Configure Postfix

Step 10: Integrate OpenDKIM with Postfix

Open the Postfix configuration:

vi /etc/postfix/main.cf

Add the following:

smtpd_milters = inet:127.0.0.1:8892
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
milter_protocol = 2

The configuration tells Postfix to send mail through the OpenDKIM Milter service running on:

127.0.0.1:8892

Validate the Postfix configuration

Run:

postfix check

You can also verify the configured Milter parameters:

postconf | grep milter

Expected output should include:

milter_default_action = accept
milter_protocol = 2
non_smtpd_milters = $smtpd_milters
smtpd_milters = inet:127.0.0.1:8892

Step 11: Start and Enable OpenDKIM

Start OpenDKIM:

service opendkim start

Enable it at boot:

chkconfig opendkim on

Check the service:

service opendkim status

Verify that OpenDKIM is listening on port 8892:

netstat -lntp | grep 8892

Expected output should show OpenDKIM listening on localhost.


Step 12: Restart Postfix

Restart Postfix:

service postfix restart

Check the status:

service postfix status

If Postfix fails to start, check the configuration:

postfix check

and review the mail logs.

On CentOS systems, the Postfix mail log is commonly:

/var/log/maillog

Verification

Step 13: Check OpenDKIM Logs

Monitor the mail log:

tail -f /var/log/maillog

When an outgoing message is successfully signed, you should see an entry similar to:

opendkim[5644]: 5FF7E161215: DKIM-Signature field added (s=default, d=domain.tld)

This confirms that OpenDKIM added a DKIM signature to the outgoing message.


Step 14: Verify the Email Headers

Send an email from:

user@domain.tld

to an external mailbox such as Gmail.

Open the received email and inspect the message headers.

A successful authentication result may look similar to:

DKIM-Signature: v=1; a=rsa-sha256; d=domain.tld; s=default; ...

The receiving mail server may also show:

DKIM: PASS

The exact header format and authentication results depend on the receiving mail provider.


Step 15: Test Using an Email Authentication Verifier

You can also send an email to an email authentication testing service such as:

check-auth@verifier.port25.com

The service can return authentication results for the submitted message, including DKIM, SPF, and other mail authentication information.


Configuring DKIM for Multiple Domains

If the same Postfix server sends emails for multiple domains, each domain can have its own DKIM key.

For example:

/etc/opendkim/keys/domain1.tld/
/etc/opendkim/keys/domain2.tld/
/etc/opendkim/keys/domain3.tld/

Each domain should have its own entry in the KeyTable:

default._domainkey.domain1.tld domain1.tld:default:/etc/opendkim/keys/domain1.tld/default
default._domainkey.domain2.tld domain2.tld:default:/etc/opendkim/keys/domain2.tld/default
default._domainkey.domain3.tld domain3.tld:default:/etc/opendkim/keys/domain3.tld/default

The SigningTable can then contain:

*@domain1.tld default._domainkey.domain1.tld
*@domain2.tld default._domainkey.domain2.tld
*@domain3.tld default._domainkey.domain3.tld

Each domain must also have its corresponding DKIM public key published in DNS.


Troubleshooting

OpenDKIM is not running

Check the service:

service opendkim status

Check the logs:

tail -100 /var/log/maillog

Check whether port 8892 is listening:

netstat -lntp | grep 8892

Postfix cannot connect to OpenDKIM

Verify the Postfix configuration:

postconf | grep milter

Verify OpenDKIM is listening:

netstat -lntp | grep 8892

Make sure both configurations use the same address and port:

Postfix:
inet:127.0.0.1:8892

OpenDKIM:
inet:8892@localhost

DKIM signature is not being added

Check the OpenDKIM logs:

grep -i opendkim /var/log/maillog

Verify:

/etc/opendkim/KeyTable
/etc/opendkim/SigningTable
/etc/opendkim/TrustedHosts

Also verify the private key permissions:

ls -l /etc/opendkim/keys/domain.tld/default

The key should be readable by the opendkim user.


DNS DKIM record is not found

Run:

dig TXT default._domainkey.domain.tld +short

If there is no response:

  1. Verify the DNS record name.
  2. Verify the TXT record value.
  3. Confirm that the DNS change was saved.
  4. Check the DNS provider’s propagation status.
  5. Confirm that the selector is default.

Security Recommendations

The DKIM private key is highly sensitive and must be protected.

Recommended permissions:

chown opendkim:opendkim /etc/opendkim/keys/domain.tld/default
chmod 600 /etc/opendkim/keys/domain.tld/default

Do not:

  • Publish the private key in DNS.
  • Share the private key with external users.
  • Store the private key in publicly accessible directories.
  • Commit the private key to Git repositories.
  • Expose the OpenDKIM Milter port publicly.

Since the Milter is configured to listen on localhost, it should not normally be exposed to external networks.


Conclusion

Configuring DKIM with OpenDKIM and Postfix adds an important layer of authentication to outgoing email. OpenDKIM generates a cryptographic signature using the private DKIM key, while receiving mail servers use the corresponding public key published in DNS to verify the signature.

The complete process consists of installing OpenDKIM, generating a domain-specific key pair, configuring the KeyTable and SigningTable, defining trusted hosts, publishing the public key in DNS, and integrating OpenDKIM with Postfix through the Milter interface.

After completing the configuration, always verify the setup using the mail server logs and the headers of a received email. A successful configuration should show a valid DKIM-Signature and, on the receiving server, a DKIM PASS result.

DKIM should also be used together with SPF and DMARC to provide a more complete email authentication and anti-spoofing strategy.

With Postfix, OpenDKIM, DNS, SPF, and DMARC correctly configured, organizations can improve the authenticity, security, and deliverability of their outgoing emails.

Leave a Reply