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.

Note, that dkim-filter is also known as dkim-milter (DomainKeysIndentifiedMail-MailFilter).
opendkim, is a fork of dkim-milter, and can be used instead.
It uses the same config parameters as dkim-filter, and the config files are named /etc/default/opendkim and /etc/opendkim.conf instead. opendkim have a better update cycle, and could therefor be a better choise!

Installing DKIM and SPF for use with postfix

aptitude install dkim-filter postfix-policyd-spf-python
Note, after installing dkim-filter, 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, dkim-filter

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.

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.
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.
aptitude install spfmilter
After this, edit the /etc/default/spfmilter file, to run as a socket, and select a port which is NOT in use. You can test this with telnet, or netstat.
you can also make it run on an IP, so it can be used infront of an SMTP.
Important that the line "DAEMON_OPTS=" looks like this, so that --markonly is removed, or else it with only mark the email, and not reject it in case that the sender have setup SPF as hardfail.
SOCKET="inet:54321@localhost" # listen just on loopback on port 54321
Save the file, and restart spfmilter
/etc/init.d/spfmilter restart
Now setup postfix, and add the spfmilter. Remember to use the same socket as in the configuration!
If you already have an milter, you can seperate it with a comma (,).
smtpd_milters                   = 

non_smtpd_milters               = 
Restart postfix
/etc/init.d/postfix restart
You can now test by sending an spoofed e-mail from example http://www.deadfake.com.
Note, that the domain you are trying to spoof must have setup SPF and must use hardfail, or else the mail will not be rejected.

Example of an rejected e-mail by SPF.
Dec 24 23:03:40 server postfix/smtpd[18674]: NOQUEUE: milter-reject: \
MAIL from zebra732.startdedicated.com[]: 550 5.7.1 rejected by spfmilter; \
from= proto=ESMTP helo=

Do not trust the authors words! POC, tests and experience is key

Copyright LinuxLasse.net 2009 - 2018 All Rights Reserved.

Valid HTML 4.01 Strict Valid CSS!