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 [email protected]
sends an e-mail to [email protected]
, and our Postfix server on myserver.example.com
forwards this e-mail to [email protected]
. 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!