Distroname and release: Debian Squeeze

Postfix with DKIM (OpenDKIM) and SPF

DKIM, and SPF are great ways for securing that your domain is not being used for spoof mails.
You should note, that this is only working as inteded if the recieveing server supports this.


DKIM and SPF are two completely different things. DKIM, is a way of signing the email itself. If the SMTP server at the recievers end then supports DKIM verifying, it can verify the public signature from the DNS TXT value with the value in the e-mail.
SPF, is a way of telling the e-mail systems which hosts are allowed to send e-mails from a specific domain. If the SMTP server at the receivers end supports SPF, it can check if the e-mails come from one of the allowed servers, and take action.

There's some quite good info here.

Installing DKIM for use with postfix

apt-get install opendkim
Note, after installing opendkim, you might get the warning shown belown.
This is because signing is not currently setup, at this time, which we want.
"Starting for DKIM verification only"

Configuring DKIM, opendkim

We have to generate a key for use with DKIM.
dkim-genkey -d mail.example.com
If will generate two files, for use with DKIM. A private key, and a public key.
The public key should be used for our public DNS for verifying, and the private key for signing.
default.private  default.txt
Next create a directory for holding the private key file, and copy the file to the directory.
mkdir /etc/postfix/dkim
cp default.private  /etc/postfix/dkim/examplecom_default.private
Now for the main configuration of DKIM, which is located in /etc/dkim-filter.conf.
Edit or uncomment the file, so the active lines in the config file, looks something similar to this.
"Selector" is "default" unless something else is specified in the -s parameter when we generated the keys with the dkim-genkey tool.
I have enabled logging of the verification status of e-mails. It is actually only recommended for debugging, but my server is not that busy, and I like to see the DKIM status.
syslog			yes
SysLogSuccess           yes #recommended for debugging only.

Domain		example.com
KeyFile		/etc/postfix/dkim/examplecom_default.private
Selector	default
Next we will setup the listening IP and port for dkim-filter, this is done in /etc/default/dkim-filter
Edit or uncomment the file, remember to set the IP to your own IP.
It is possible to use unixsocket instead, which should perform better. But because postfix runs in chroot, both postfix and dkim, must be able to read the file.
SOCKET="inet:12345@" # listen on on port 12345
Setup postfix to listen on the DKIM filter, by adding the following to the main.cf file.
smtpd_milters                   = 

non_smtpd_milters               = 
Now we have to setup the DNS for our domain. Check the file default.txt, and note the values for TXT and the key. (I have stripped quite a lot of the key)
cat default.txt
default._domainkey IN TXT "v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC....AB" \
; ----- DKIM default for example.com
Now create a TXT DNS record at your DNS host, as this. (again, the key is stripped). Note I have added t=y which makes DKIM run in test mode. This means that even if the verification fails, the mail will still be delivered. When eveything is OK, remove the t=y parameter.
host:		default._domainkey
string:		v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC....AB; t=y
All done, now restart dkim-filter and postfix.
The warning message that tells it runs for verification only should now be gone.
/etc/init.d/dkim-filter restart
/etc/init.d/postfix restart


The absolute easiest way to test the signing function, is to send an e-mail to an g-mail account.
If it is successfull, you should get an "signed by example.com" in the detailed view of the e-mail.
The reason to do so, is that gmail supports DKIM verifying. If the SMTP reciever does not support DKIM, have no worries. The e-mail will be delivered, but not checked for DKIM.

If you have logging enabled you could check the mail.log file.
This does not verify if it is working as inteded, just if the signature is added to the e-mail!
If it is not working, it could be that the signature is wrong on the DNS host, but the header will still be added.
So until you are sure that everything is working, add the "t=y" parameter to the DKIM txt DNS entry, as mentioned earlier.

This shows, that signing is OK.
tail -f /var/log/mail.log |grep -i dkim
Sep 23 17:13:50 myServer dkim-filter[3079]: C27E761E5A8 "DKIM-Signature" header added
For verification, try to send an e-mail from the gmail account, and then check the mail.log for messages.
tail -f /var/log/mail.log |grep -i dkim
Sep 23 17:05:18 myServer dkim-filter[3079]: 982BD39E5B9 DKIM verification successful

dkim-filter / dkim-milter and ClamSMTP

Doing my tests, I discovered that dkim-filter, added the signature twice to the e-mail header.
It also checked the verification twice. This was due to ClamSMTP, so I edited the /etc/postfix/master.cf file to not add the milter, when the e-mails is injected into postfix again.

It did actually work, but it is quite a bid overhead in a busy server, and actually quite stupid to check it twice, and add two signatures into the header of the e-mail.

Add "no_milters" to the recieve_overrride_options line, like below.

Installing SPF for postfix

Installtion, and setup is actually quite straight forward.
apt-get install postfix-policyd-spf-perl

Configuring SPF

First we will start by creating an TXT record. Below are the options.
  • ?all = neutreal, which is for testing purposes where we do not want other SMTPs to block us.
  • ~all = softfail, will normally mark the SPF check as failed, but still be delivered.
  • -all = hardfail, will mark the SPF check as failed, and reject the mail. After testing, this is want we want.
I'll recommend using a spf wizard / generator, just google for it, there are plenty out there.

Create it as an TXT record on your DNS host.
An example could looke like this, meaning that all MX's configured for this domain is allowed to send. It is also possible to add IP's if we want a server which is not an MX to allow to send mail.
Note we are using an hardfail here, this should only normally be used after testing!
"v=spf1 mx -all"
Now we will install the spfmilter/spffilter on the server running postfix.
All information here, are from the man page! "man postfix-policyd-spf-perl"

Add configuration to postfix master.cf file
 spfcheck  unix  -       n       n       -       0       spawn
   user=policyd-spf argv=/usr/sbin/postfix-policyd-spf-perl
Add configuration to main.cf. Notice, that you will hightly likely have other configuration parameters here!
Be sure to add the check_policy_service under reject_unauth_destination, or you might become an open-relay!
smtpd_recipient_restrictions =
     check_policy_service unix:private/spfcheck,
Set spfcheck timeout
postconf -e spfcheck_time_limit=3600
Restart postfix
/etc/init.d/postfix restart


Testing can be done by using the postfix-policyd-spf-perl binary!

client_address=[EXT. IP OF SERVER]
client_name=[FQDN of Mailserver]
Output would show something like this!(ips whiped)..
action=PREPEND Received-SPF: pass (linuxlasse.net: xxx.xxx.xxx.xxx is authorized to use 'foo@linuxlasse.net' in \
'mfrom' identity (mechanism 'mx' matched)) receiver=mailobie; identity=mailfrom; \ 
envelope-from="foo@linuxlasse.net"; helo=test.example.com; client-ip=xxx.xxx.xxx.xxx
Here is an real-life log, from the mailserver, on an ingoing e-mail.
Nov  2 10:36:20 mailobie postfix/policy-spf[4441]: Policy action=PREPEND Received-SPF: pass \
(hotmail.com: Sender is authorized to use 'example@hotmail.com' in \
'mfrom' identity (mechanism 'include:spf.protection.outlook.com' matched)) receiver=mailobie; identity=mailfrom; \
envelope-from="example@hotmail.com"; helo=EUR03-AM5-obe.outbound.protection.outlook.com; client-ip=
And/Or test by sending an spoofed e-mail from example http://www.deadfake.com.
Do not trust the authors words! POC, tests and experience is key

Copyright LinuxLasse.net 2009 - 2021 All Rights Reserved.

Valid HTML 4.01 Strict Valid CSS!