Setting Up DKIM And SRS In Postfix
In my previous post Custom Domain E-mails With Postfix And Gmail: The Missing Tutorial, we set up a Postfix mail server on a custom domain that integrates seamlessly with Gmail.
However, the tutorial skipped two important security standards that will help prevent e-mails routed through our server from being marked as spam: DKIM and SRS. This article will show you how to add support for DKIM and SRS to a Postfix server.
Similar to the previous tutorial, we will assume a Ubuntu server in our examples.
Step 1: DKIM
DKIM, short for DomainKeys Identified Mail, is a mechanism for
-
A sender e-mail program to sign an outgoing e-mail message, and
-
A recipient e-mail program to verify said signature.
More concretely, let’s say Gmail receives an e-mail message from myserver.example.com. DKIM allows Gmail to verify that the e-mail was indeed sent by the designated e-mail server program on myserver.example.com, and not by, say, a virus running on myserver.example.com or a malicious user who happens to have access to myserver.example.com.
We will use OpenDKIM for this tutorial. To install OpenDKIM on Ubuntu:
$ sudo apt-get install opendkim opendkim-tools
/etc/opendkim.conf
Edit /etc/opendkim.conf to match the following:
# OpenDKIM config.
# Log to syslog
Syslog yes
SyslogSuccess yes
LogWhy yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask 002
Mode sv
PidFile /var/run/opendkim/opendkim.pid
UserID opendkim:opendkim
Socket inet:12301@localhost
Canonicalization relaxed/simple
SignatureAlgorithm rsa-sha256
# Sign for example.com with key in /etc/opendkim.d/mail.private using
# selector 'mail' (e.g. mail._domainkey.example.com)
Domain example.com
KeyFile /etc/opendkim.d/mail.private
Selector mail
ExternalIgnoreList refile:/etc/opendkim.d/TrustedHosts
InternalHosts refile:/etc/opendkim.d/TrustedHosts
You can check out a detailed explanation for the meaning of each option with man opendkim.conf.
/etc/opendkim.d/TrustedHosts
Create the directory /etc/opendkim.d and put the following in /etc/opendkim.d/TrustedHosts. This instructs the OpenDKIM server to sign e-mails delivered by any server matching these expressions (such as myserver_2.example.com).
127.0.0.1
::1
localhost
192.168.0.1/24
*.example.com
DKIM keys
Now, let’s generate our DKIM signing keys:
$ cd /etc/opendkim.d
$ sudo opendkim-genkey -s mail -d example.com
This will produce two files in /etc/opendkim.d: our private key, mail.private, and our public key, mail.txt.
We should make sure only OpenDKIM can read the private key, so that a malicious program or user on the same server won’t be able to forge our signature:
$ chmod 600 mail.private
$ chown opendkim:opendkim mail.private
DKIM public key DNS record
The next step is to publish our public key through DNS, so that any recipient e-mail program can verify our signature. If we look at our public key mail.txt generated in the previous step, it should look like something like this:
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=<alphabetical soup>" ) ; ----- DKIM key mail for example.com
Create the following TXT DNS record for example.com (how to update DNS records will depend on the DNS hosting provider):
-
Name:
mail._domainkey.example.com -
Value:
v=DKIM1; k=rsa; p=<alphabetical soup>
where <alphabetical soup> is the public key found in mail.txt after p=. Note that DNS records will take a while (depending on our provider, up to a day) to propagate.
OpenDKIM server
We can now start the OpenDKIM server with
$ sudo /etc/init.d/opendkim start
Postfix
The last step is to tell Postfix to use OpenDKIM to sign outgoing e-mail messages. Add the following to /etc/postfix/main.cf:
# Milter settings.
milter_protocol = 2
milter_default_action = accept
# OpenDKIM runs on port 12301.
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301
If you already have other milters configured (such as SpamAssassin), simply add inet:localhost:12301 to your existing smtpd_milters and non_smtpd_milters lines, prefixed by a comma.
Let’s now restart Postfix with the new configuration:
$ sudo postfix reload
…and we’re done!
Step 2: SRS
SRS, short for Sender Rewriting Scheme, is a standard for including forwarding / relay information in a forwarded / relayed e-mail message.
For example, suppose alice@hotmail.com sends an e-mail to john@example.com, and our Postfix server on myserver.example.com forwards this e-mail to john123@gmail.com. SRS allows our Postfix server on myserver.example.com to attach a virtual sticky note on the e-mail message explaining this situation to Gmail. Otherwise, Gmail might become suspicious of why myserver.example.com is producing messages that purport to come from hotmail.com, which spammers and phishers are wont to do.
We will use PostSRSd to implement SRS in our Postfix server. It works out of the box with Postfix and is a breeze to set up, but unfortunately is not included in the official Ubuntu / Debian package repositories.
OpenSRSd
Let’s build and install OpenSRSd from source:
# Dependencies.
$ sudo apt-get install unzip cmake
# Download and extract source code from GitHub.
$ cd /tmp
$ curl -L -o postsrsd.zip \
https://github.com/roehling/postsrsd/archive/master.zip
$ unzip postsrsd.zip
# Build and install.
$ cd postsrsd-master
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/usr ../
$ make
$ sudo make install
The default config provided by PostSRSd (/etc/default/postsrsd) will pretty much work out of the box for our case.
The install script will also conveniently install an Upstart script for PostSRSd. Let’s start it now:
$ sudo service postsrsd start
Postfix
Finally, we configure Postfix to use PostSRSd. Add the following to /etc/postfix/main.cf:
# PostSRSd settings.
sender_canonical_maps = tcp:localhost:10001
sender_canonical_classes = envelope_sender
recipient_canonical_maps = tcp:localhost:10002
recipient_canonical_classes= envelope_recipient,header_recipient
And restart Postfix with the new configuration:
$ sudo postfix reload
That’s it!