Debian: Postfix + DKIM

OpenDKIM is an open source implementation of the DKIM (Domain Keys Identified Mail) sender authentication system proposed by the E-mail Signing Technology Group (ESTG), now standardized by the IETF (RFC6376). It also includes implementations of the RFC5617) Vouch By Reference (VBR, RFC5518) proposed standard and the experimental Authorized Third Party Signatures protocol (ATPS, RFC6541).

Step 1: Install Packages

First, make sure that OpenDKIM is installed. On a Debian instance, you can do this with:

# apt install opendkim opendkim-tools
# apt install libdigest-sha-perl libdigest-sha-perl libcrypt-openssl-rsa-perl liberror-perl perl libnet-dns-perl libnet-server-perl libmail-dkim-perl libmailtools-perl

Step 2: Configure Basics

Add user postfix to OpenDKIM

# adduser postfix opendkim

Create the opendkim socket file and change main permissions of the configuration file

# mkdir -p /var/spool/postfix/opendkim/
# chown opendkim:opendkim /var/spool/postfix/opendkim/

Edit the OpenDKIM configuration file /etc/opendkim.conf

Syslog           yes
Selector         mail
Mode             sv
SubDomains       yes
Socket           local:/var/spool/postfix/opendkim/opendkim.sock
PidFile          /var/run/opendkim/opendkim.pid
OversignHeaders  From
TrustAnchorFile  /usr/share/dns/root.key
UserID           opendkim
LogWhy           yes
Canonicalization          relaxed/simple
KeyTable                  /etc/opendkim/KeyTable
SigningTable              /etc/opendkim/SigningTable
ExternalIgnoreList        /etc/opendkim/TrustedHosts
InternalHosts             /etc/opendkim/TrustedHosts

Create opendkim configuration subdirectory and set its permissions::

# mkdir /etc/opendkim

Step 3: Define TrustedHosts

Edit the OpenDKIM Trusted Hosts configuration file /etc/opendkim/TrustedHostsand define the whitelist/trusted host list

127.0.0.1
localhost
192.168.0.0/255.255.255.0
<my-external-ip>
<my-mailserver-ip>
domain.com

Step 4: Define SigningKey

Generate a key for the domain: <domain.com> = your domain name.

# mkdir -p /etc/opendkim/keys/
# cd /etc/opendkim/keys/
# opendkim-genkey -b 2048 -d  -s mail
# chown opendkim:opendkim -R /etc/opendkim
# chmod 600 /etc/opendkim/keys/domain/mail.private

Edit the OpenDKIM Keytable /etc/opendkim/KeyTableand define the key location:

mail._domainkey.<domain.com> <domain.com>:mail:/etc/opendkim/keys/<domain.com>/mail.private

Edit the OpenDKIM SigningTable /etc/opendkim/SigningTableand specify which key will sign

<domain.com> mail._domainkey.<domain.com>

Step 5: DNS Configuration

Print key:

# cat /etc/opendkim/keys/domain.com/mail.txt

Copy and paste printed key to your domain.com config file in DNS server (Bind9 – domain.com)

mail._domainkey IN TXT "v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3... ...DQEBAQUAA4GNAB" ; ----- DKIM default for domain.com

Restart the dns server

# systemctl restart opendkim

Step 6: Configure Postfix

Edit the postfix configuration file /etc/postfix/main.cf

milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:/opendkim/opendkim.sock
non_smtpd_milters = unix:/opendkim/opendkim.sock

Restart postfix

# systemctl restart postfix

Step 7: (Optional) Author Domain Signing Practices (ADSP)

As a final item, you can add an ADSP policy to your domain saying that all emails from your domain should be DKIM-signed. As usual, it’s done with a TXT record for host _adsp._domainkey in your domain with a value of dkim=all. If you’re using Linode’s DNS Manager, the screen for the new text record will look like this:

_adsp._domainkey.domain.com   IN    TXT    "dkim=unknown"

You don’t need to set this up, but doing so makes it harder for anyone to forge email from your domains because recipient mail servers will see the lack of a DKIM signature and reject the message.

Step 8: (Optional) Message Authentication,Reporting & Conformance

The DMARC DNS record can be added to advise mail servers what you think they should do with emails claiming to be from your domain that fail validation with SPF and/or DKIM. DMARC also allows you to request reports about mail that fails to pass one or more validation check. DMARC should only be set up if you have SPF and DKIM set up and operating successfully. If you add the DMARC DNS record without having both SPF and DKIM in place, messages from your domain will fail validation which may cause them to be discarded or relegated to a spam folder.

The DMARC record is a TXT record for host _dmarc in your domain containing the following recommended values:

v=DMARC1;p=quarantine;sp=quarantine;adkim=r;aspf=r

This requests mail servers to quarantine (do not discard, but separate from regular messages) any email that fails either SPF or DKIM checks. No reporting is requested. Very few mail servers implement the software to generate reports on failed messages, so it is often unnecessary to request them. If you do wish to request reports, the value would be similar to this example, added as a single string:

v=DMARC1;p=quarantine;sp=quarantine;adkim=r;aspf=r;fo=1;rf=afrf;rua=mailto:user@example.com

Replace user@example.com in the mailto: URL with your own email or an email address you own dedicated to receiving reports (an address such as dmarc@example.com). This requests aggregated reports in XML showing how many messages fell into each combination of pass and fail results and the mail server addresses sending them. If you’re using Linode’s DNS Manager, the screen for the new text record will look like this:

DMARC records have a number of available tags and options. These tags are used to control your authentication settings:

  • v specifies the protocol version, in this case DMARC1.
  • p determines the policy for the root domain, such as “example.com.” The available options:
    • quarantine instructs that if an email fails validation, the recipient should set it aside for processing.
    • reject requests that the receiving mail server reject the emails that fail validation.
    • none requests that the receiver take no action if an email does not pass validation.
  • sp determines the policy for subdomains, such as “subdomain.example.com.” It takes the same arguments as the p tag.
  • adkim specifies the alignment mode for DKIM, which determines how strictly DKIM records are validated. The available options are:
    • r relaxed alignment mode, DKIM authentication is less strictly enforced.
    • s strict alignment mode. Only an exact match with the DKIM entry for the root domain will be seen as validated.
  • aspf determines the alignment mode for SPF verification. It takes the same arguments as adkim.

If you wish to receive authentication failure reports, DMARC provides a number of configuration options. You can use the following tags to customize the formatting of your reports, as well as the criteria for report creation.

  • rua specifies the email address that will receive aggregate reports. This uses the mailto:user@example.com syntax, and accepts multiple addresses separated by commas. Aggregate reports are usually generated once per day.
  • ruf specifies the email address that will receive detailed authentication failure reports. This takes the same arguments as rua. With this option, each authentication failure would result in a separate report.
  • fo allows you to specify which failed authentication methods will be reported. One or more of the following options can be used:
    • 0 will request a report if all authentication methods fail. For example, if an SPF check were to fail but DKIM authentication was successful, a report would not be sent.
    • 1 requests a report if any authentication check fails.
    • d requests a report if a DKIM check fails.
    • s requests a report if an SPF check fails.
  • rf determines the format used for authentication failure reports. Available options:
    • afrf uses the Abuse Report format as defined by RFC 5965.
    • iodef uses the Incident Object Description Exchange format as defined by RFC 5070.

Key Rotation

The reason the YYYYMM format is used for the selector is that best practice calls for changing the DKIM signing keys every so often (monthly is recommended, and no longer than every 6 months). To do that without disrupting messages in transit, you generate the new keys using a new selector.

Testing.

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