Table of Contents

Postfix - OpenDKIM configuration

How to configure DKIM ?

This page is a step by step page that will show you how to sign outgoing email with the DKIM specification.

OpenDKIM will sign the email passed by Postfix and every receiver can check the email authenticity through the public key published in the DNS record of the domain.

The signature is added in the email in an header field. Example:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytle.net;
	s=vps748761.ovh.net; t=1591988898;
	bh=WBggpZrfs7F0OzQkyE7LiZPHyfFFhl7N4CNav2f5YVw=;
	h=Date:To:Subject:From:From;
	b=ByN4Iw4U9RP8bzaPK0n3HJbFlvI60ett+V9pkoli+UNtdAcSdq/ANc3hL71PzjrT4
	 3yyTjK3MC5e2f/k+BAnIaAgnradAK/1CbMF4vMZVD6WoVIx7KTZlfWsW39Ir8PhqYQ
	 4TKvPpDUx8ToxUz1gwQlxJoExYW3McXJ2WdvUAf8=

The configuration is done with OpenDkim installed as a milter software of Postfix (for the MTA) on a CentsOS (Redhat) linux box.

Steps

To install opendkim as a milter to an MTA, you need to perform the following steps:

Installation

If you want to install it from the source. See the install doc

yum install -y opendkim

Generate the key and the DNS record with opendkim-genkey

The opendkim-genkey will:

The private key signs the message (ie encrypt) and the public key can decrypt it.

As there is only one public key that can decrypt a message encrypted by the private key, the authenticity of the sender can then be verified.

This is a feature of the Public Key Cryptography system.

Syntax:

opendkim-genkey -s SELECTOR -d DOMAIN
# example with your brand name
opendkim-genkey -s brandName -d example.com

where:

If you want to test it, you can add the --testmode argument.

testmode tells the verifiers that they should not take any real action based on success or failure of the use of this key after verifing a message.

In the generated TXT record, you will find back a t=y that you can remove to enter in production mode.

Two files should have been generated:

Verification of the file existence:

cat brandName.txt
yourSelector._domainkey	IN	TXT	( "v=DKIM1; k=rsa; "
	  "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQUtHxTD63yxwq5fmjJ3RtXw2NP5/QEiSq3Xx85faTHnnj3/PA/igwWaueDsoeUuZOpkL74gDNGWBoQPecRaFrAXdPoEKGDYNBeMXzIkWQOth9Oaq4N+38LV08Ui86so8B2BhcvgXiqpACsrPur0hbDQWI183tZve7MKMPs3KPIQIDAQAB" )  ; ----- DKIM key vps748761.ovh.net for bytle.net
ll brandName.private
-rw------- 1 root root 887 Jun 12 12:03 vps748761.ovh.net.private

DNS Zone

The next step is to publish the public key by creating a TXT DNS record with the help of the generated TXT file.

DNS DKIM value explained

The TXT record value generated has the form:

"v=DKIM1; k=rsa; " "p=public key"

where :

DNS DKIM Creation

If the DNS interface of your provider supports TXT input, you can just take the input of the TXT file and add it at the end.

Dkim Record Text Format Ovh Dns Zone

Then you should see a TXT record with a DKIM value. Example with a snapshot of the DNS manager of my domain provider

Dns Zone Dkim Public Key

where the public key DNS record should appear as a TXT resource record as:

SELECTOR._domainkey.DOMAIN
# in the snapshot
vps748761.ovh.net._domainkey.bytle.net.

where:

DOMAIN may also be specified:

DNS DKIM record test

You can verify that the key matches the private key with opendkim-testkey

opendkim-testkey -d DOMAIN -s $(hostname) -k $(hostname).private
# example
opendkim-testkey -d bytle.net -s $(hostname) -k $(hostname).private

If you got no message and an exit code of zero, that's all good.

echo $?
0

Private key

The key should be stored in a safe place.

mv $(hostname).private /etc/opendkim/keys
# The opendkim was created with the package installation
chown opendkim:opendkim /etc/opendkim/keys/ # should already by the case
chown opendkim:opendkim  /etc/opendkim/keys/$(hostname).private
chmod 0700 /etc/opendkim/keys # 0=rwx
chmod 0600 /etc/opendkim/keys/$(hostname).private # o=rw

OpenDKIM Configuration

The minimal configuration for OpenDKIM defines:

FYI: The global configuration file can be found at:

/etc/opendkim.conf

Socket selection

The MTA and your opendkim filter communicate over a socket connection.

You can choose to use:

In case of a tcp socket, for selinux, the following command will need to be executed as the superuser, which declares the chosen port to be a milter application port:

# to see if SELINUX is enable
# cat /etc/selinux/config | grep -i SELINUX=
# if yes then
semanage port -a -t milter_port_t -p tcp <port>

The actual socket configuration of OpenDKIM is

##  Create a socket through which your MTA can communicate.
Socket	inet:8891@localhost

Mapping Key to Domain

KeyTable

OpenDKIM find the private keys with the KeyTable lookup file. It's a file that maps key names to signing keys. (private key)

Conf:

KeyTable refile:/etc/opendkim/KeyTable

SELECTOR._domainkey.DOMAIN DOMAIN:SELECTOR:/path/to/my/key
# or with this actual step by step
SELECTOR._domainkey.DOMAIN DOMAIN:SELECTOR:/etc/opendkim/keys/SELECTOR.private

It requires SigningTable be enabled.

SigningTable

This SigningTable is a file that maps:

Conf:

SigningTable refile:/etc/opendkim/SigningTable

# Wild card example (refile scheme)
*@DOMAIN SELECTOR._domainkey.DOMAIN

Operating mode

The operating modes are:

You need to change it at minimal to s in order to sign the email.

Mode	sv

Signing external mail

Optional

If you wish to sign mail that comes from sources other than the localhost address (127.0.0.1), include these in CIDR notation in the configuration file for the InternalHosts configuration option.

##  Identifies a set "internal" hosts whose mail should be signed rather than verified.
InternalHosts refile:/etc/opendkim/TrustedHosts

##  Identifies a set of "external" hosts that may send mail through the server as one
##  of the signing domains without credentials as such.
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts

MTA configuration (Postfix )

Email - Postfix

smtpd_milters

Syntax:

smtpd_milters = inet:localhost:portnumber ...other filters...

With the OpenDkim Socket configuration of this tutorial (the default)

smtpd_milters = inet:localhost:8891

non_smtpd_milters

The non-SMTP Milter applications handle mail that arrives via:

non_smtpd_milters = inet:localhost:8891

Error handling

Optional

The milter_default_action property defines what to do in case of errors.

The following value can be chosen:

milter_default_action = tempfail

Restart

Restart the services

systemctl restart opendkim
systemctl restart  postfix

Test

To test, we need to send an email and to see if the DKIM header was added.

If the test does not work, check the diagnostic section.

We show two ways to test:

Install a Mail Client

The client mail used is mail that you can install with the mailx package

yum install -y mailx

It's possible to send email with the sendmail command line of postfix

Mail tester

The first easy method to test is to send an email to the mail-tester website. They will then analyze it and give you a score.

echo "Body: This is a test mail. Hallo Charlie" | mail -s "Subject: A big test" [email protected]

Opendkim Test Mailer

Gmail

Gmail allows you to see:

Send an email to your Gmail address

echo "Body: This is a test mail. Hallo Charlie" | mail -s "Subject: A big test" [email protected]

You can then verify the signing:

Gmail Original Message Dkim Test

Dkim Verification Gmail

Diagnostic

opendkim-testkey -d DOMAIN -s $(hostname) -k /etc/opendkim/keys/$(hostname).private
tail -f /var/log/maillog

Jun 12 20:57:17 vps748761 postfix/pickup[22362]: D572A1FBE8: uid=0 from=<root>
Jun 12 20:57:17 vps748761 postfix/cleanup[23285]: D572A1FBE8: message-id=<[email protected]>
Jun 12 20:57:17 vps748761 opendkim[23276]: D572A1FBE8: DKIM-Signature field added (s=vps748761.ovh.net, d=bytle.net)
Jun 12 20:57:17 vps748761 postfix/qmgr[22361]: D572A1FBE8: from=<[email protected]>, size=521, nrcpt=1 (queue active)
Jun 12 20:57:18 vps748761 postfix/smtp[23288]: D572A1FBE8: to=<[email protected]>, relay=gmail-smtp-in.l.google.com[173.194.76.27]:25, delay=0.57, delays=0.06/0/0.35/0.16, dsn=2.0.0, status=sent (250 2.0.0 OK  1591988238 r8si6848556wrn.39 - gsmtp)
Jun 12 20:57:18 vps748761 postfix/qmgr[22361]: D572A1FBE8: removed

netstat -tulpn|grep 8891
tcp        0      0 127.0.0.1:8891          0.0.0.0:*               LISTEN      21636/opendkim

postconf -h smtpd_milters # inet:localhost:8891
postconf -h non_smtpd_milters # inet:localhost:8891

Documentation / Reference

This page was created with the help of the following references: