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-perlCode language: PHP (php)
Step 2: Configure Basics
Add user postfix to OpenDKIM:
# adduser postfix opendkimCode language: PHP (php)
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/Code language: PHP (php)
Edit the OpenDKIM configuration file /etc/opendkim.conf:
# 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.
## 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 002
## Sign for example.com with key in /etc/dkimkeys/dkim.key using
## selector '2007' (e.g. 2007._domainkey.example.com)
Domain cyberfront.org
Keyfile /etc/opendkim/keys/mail.private
Selector mail
## Commonly-used options; the commented-out versions show the defaults.
SubDomains yes
## Socket socketspec
##
## Names the socket where this filter should listen for milter connections
## from the MTA. Required. Should be in one of these forms:
##
## inet:port@address to listen on a specific interface
## inet:port to listen on all interfaces
## local:/path/to/socket to listen on a UNIX domain socket
Socket inet:8891@localhost
#Socket local:/var/run/opendkim/opendkim.sock
#Socket local:/var/spool/postfix/opendkim/opendkim.sock
## PidFile filename
## default (none)
##
## Name of the file where the filter should write its pid before beginning
## normal operations.
##
PidFile /var/run/opendkim/opendkim.pid
## Always oversign From (sign using actual From and a null From to prevent
## malicious signatures header fields (From and/or others) between the signer
## and the verifier. From is oversigned by default in the Debian pacakge
## because it is often the identity key used by reputation systems and thus
## somewhat security sensitive.
OversignHeaders From
## ResolverConfiguration filename
## default (none)
##
## Specifies a configuration file to be passed to the Unbound library that
## performs DNS queries applying the DNSSEC protocol. See the Unbound
## documentation at http://unbound.net for the expected content of this file.
## The results of using this and the TrustAnchorFile setting at the same
## time are undefined.
## In Debian, /etc/unbound/unbound.conf is shipped as part of the Suggested
## unbound package
# ResolverConfiguration /etc/unbound/unbound.conf
## TrustAnchorFile filename
## default (none)
##
## Specifies a file from which trust anchor data should be read when doing
## DNS queries and applying the DNSSEC protocol. See the Unbound documentation
## at http://unbound.net for the expected format of this file.
TrustAnchorFile /usr/share/dns/root.key
## Userid userid
## default (none)
##
## Change to user "userid" before starting normal operation? May include
## a group ID as well, separated from the userid by a colon.
UserID opendkim
## Canonicalization
##
## defines the canonicalization methods used at message signing, the simple
## method allows almost no modification while the relaxed one tolerates minor
## changes such as whitespace replacement; relaxed/simple -
## the message header will be processed with the relaxed algorithm and the body with the simple one
Canonicalization relaxed/relaxed
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
## Mode
##
## Declares operating modes; in this case the milter acts as a signer (s) and a verifier (v)
Mode sv
Code language: PHP (php)
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.comCode language: HTML, XML (xml)
Step 4: Define SigningKey
Generate a key for the domain: <domain.com> = your domain name.
# mkdir -p /etc/opendkim/keys/
# cd /etc/opendkim/keys/<domain.com>
# opendkim-genkey -b 2048 -d -s mail
# chown opendkim:opendkim -R /etc/opendkim
# chmod 600 /etc/opendkim/keys/<domain.com>/mail.privateCode language: PHP (php)
Edit the OpenDKIM Keytable /etc/opendkim/KeyTableand define the key location:
mail._domainkey.<domain.com> <domain.com>:mail:/etc/opendkim/keys/<domain.com>/mail.privateCode language: HTML, XML (xml)
Edit the OpenDKIM SigningTable /etc/opendkim/SigningTableand specify which key will sign:
<domain.com> mail._domainkey.<domain.com>Code language: CSS (css)
Step 5: DNS Configuration
Print key:
# cat /etc/opendkim/keys/<domain.com>/mail.txtCode language: HTML, XML (xml)
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.comCode language: JavaScript (javascript)
Restart the opendkim service:
# systemctl restart opendkimCode language: PHP (php)
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.sockCode language: JavaScript (javascript)
Restart postfix
# systemctl restart postfixCode language: PHP (php)
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:
vspecifies the protocol version, in this caseDMARC1.pdetermines the policy for the root domain, such as “example.com.” The available options:quarantineinstructs that if an email fails validation, the recipient should set it aside for processing.rejectrequests that the receiving mail server reject the emails that fail validation.nonerequests that the receiver take no action if an email does not pass validation.
spdetermines the policy for subdomains, such as “subdomain.example.com.” It takes the same arguments as theptag.adkimspecifies the alignment mode for DKIM, which determines how strictly DKIM records are validated. The available options are:rrelaxed alignment mode, DKIM authentication is less strictly enforced.sstrict alignment mode. Only an exact match with the DKIM entry for the root domain will be seen as validated.
aspfdetermines the alignment mode for SPF verification. It takes the same arguments asadkim.
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.
ruaspecifies the email address that will receive aggregate reports. This uses themailto:user@example.comsyntax, and accepts multiple addresses separated by commas. Aggregate reports are usually generated once per day.rufspecifies the email address that will receive detailed authentication failure reports. This takes the same arguments asrua. With this option, each authentication failure would result in a separate report.foallows you to specify which failed authentication methods will be reported. One or more of the following options can be used:0will 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.1requests a report if any authentication check fails.drequests a report if a DKIM check fails.srequests a report if an SPF check fails.
rfdetermines the format used for authentication failure reports. Available options:
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 OKCode language: PHP (php)