Fighting spam can be tricky. In addition to SPF records, DKIM is nearly mandatory to help prevent sent emails from being classified as spam. Beginning February of 2024, both Google and Yahoo will require DMARC, which require either SPF or DKIM; and in some cases for a high volume of emails (5,000+), both.
In this tutorial, we will look at signed outbound messages with DKIM via use of the open source project OpenDKIM. If you followed my previous tutorial on Postfix + Dovecot + Mysql/MaraiDB, you may have multiple domain names, so this guide will assume you will want to configure separate DKIM keys for each domain name you are hosting.
Step 1: Install OpenDKIM
First, update packages for your distribution.
sudo apt-get update && sudo apt-get upgrade
Install OpenDKIM and OpenDKIM tools. OpenDKIM-tools has a utility to generate the keys we will use.
sudo apt-get install opendkim opendkim-tools
Step 2: Created trusted hosts configuration file for OpenDKIM
First, create a file that OpenDKIM will use that defines the trusted hosts that can send messages.
sudo mkdir /etc/opendkim
sudo vi /etc/opendkim/TrustedHosts
Add the IP addresses and fqdn of the server sending messages by typing i to change into insert mode in vi.
127.0.0.1
localhost
192.168.1.2
mail.mydomain.com
Type :wq to commit the changes in vi.
Step 3: Modify OpenDKIM configuration file
Modify the opendkim.conf configuration file
sudo vi /etc/opendkim.conf
Search for #Canonicalization simple and uncomment the line by removing the # symbol.
Search for #Mode and remove the # symbol to uncomment the line. Ensure the line is configured with s for signing outbound emails or sv for verifying dkim keys on sent and received emails.
If you have subdomains, search for #SubDomains and remove the # and change to yes. For example:
SubDomains yes
Search for Socket local:/var/run/opendkim/opendkim.sock and comment the line by adding a # in front of the line.
Search for #Socket inet:8891t@localhost and uncomment the line. If the line does not exist in your document, then add the following at the end of your document.
Socket inet:8891@localhost
Next, add the following lines to reference our DKIM configurations for each domain:
KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
Type :wq to save the change and close the file
Step 4: Configure Postfix
sudo vi /etc/postfix/main.cf
Add the following lines to the end of the file:
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Type :wq to save the changes and close the file.
Step 5: Restart services to use the changes (optional)
Execute the following to apply the changes if you wish to add domain names at a later time. If not, you can skip this step.
sudo /etc/init.d/opendkim restart
sudo /etc/init.d/postfix reload
sudo /etc/init.d/postfix restart
Step 5/6: Create a DKIM key for a domain
Run the following command to create a new folder and change directory to it for where we will generate our key used to sign the outgoing emails.
sudo mkdir -p /etc/opendkim/keys/mydomain.com
cd /etc/opendkim/keys/mydomain.com
Execute the following command to generate the key:
sudo opendkim-genkey -r -d mydomain.com
Delegate access to the opendkim user and group to access the key (note, if you modified the user in your opendkim.conf file, you will want to use that instead)
sudo chown opendkim:opendkim default.private
Step 7: Reference the key via OpenDKIM KeyTable
Modify the Keytable with vi
sudo vi /etc/opendkim/KeyTable
Add the following line to the file to define your selector. In this example, we will call the selector default, but if your domain requires multiple DKIM keys, ensure you make this unique. You can modify the file by pressing i to enter insert mode in vi:
default._domainkey.mydomain.com mydomain.com:default:/etc/opendkim/keys/mydomain.com/default.private
Type :wq to write and quite vi
Step 8: Specify the domain in your OpenDKIM SigningTable
Open the SigningTable file via vi
sudo vi /etc/opendkim/SigningTable
Add the following line to the file by pressing i to enter insert mode (changing default if specified a different selector earlier on):
mydomain.com default._domainkey.mydomain.com
Type :wq to write and quite vi
Step 8: Update your services to apply the changes
Restart your services to begin signing your messages:
sudo /etc/init.d/opendkim restart
sudo /etc/init.d/postfix reload
sudo /etc/init.d/postfix restart
Step 9: Update DNS
Get the DNS record values we need to publish by executing the following command:
sudo cat /etc/opendkim/keys/mydomain.com/default.txt
Create a new TXT record within your nameservers and specify the value between the quotes (don't include the quotes). I.e.:
v=DKIM1; h=sha256; k=rsa; s=email; p=ABCDEFG.....
Note: I choose to update DNS last as once you update DNS, any servers that would receive mail before you apply the previous configuration may discard your emails. Then again, you didn't have DKIM before, so you were probably going to junk mail anyways ;^)
Credits
Shoutout to Diego on stackoverflow, edoceo, and suenotek for consolidating a lot of these steps:
postfix - Using DKIM in my server for multiple domains (websites) - Ask Ubuntu
How To: Installing and Configuring OpenDKIM for multiple domains with Postfix on Linux | Edoceo
Roundcube mail app and SPF, DKIM & DMARC on Ubuntu 20.04 (suenotek.com)