Distroname and release: Debian Squeeze
Postfix with DKIM (OpenDKIM) and SPFDKIM, 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 vs SPFDKIM 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-pythonNote, 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-filterWe have to generate a key for use with DKIM.
dkim-genkey -d mail.example.comIf 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.
ls default.private default.txtNext 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.privateNow 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.
/etc/dkim-filter.conf syslog yes SysLogSuccess yes #recommended for debugging only. Domain example.com KeyFile /etc/postfix/dkim/examplecom_default.private Selector defaultNext 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.
/etc/default/dkim-filter SOCKET="inet:firstname.lastname@example.org" # listen on 127.0.0.1 on port 12345Setup postfix to listen on the DKIM filter, by adding the following to the main.cf file.
/etc/postfix/main.cf smtpd_milters = inet:localhost:12345 non_smtpd_milters = inet:localhost:12345Now 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.comNow 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=yAll 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
TestingThe 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: C27E761E5A8 "DKIM-Signature" header addedFor 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: 982BD39E5B9 DKIM verification successful
dkim-filter / dkim-milter and ClamSMTPDoing 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 SPFFirst 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.
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 spfmilterAfter 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.
/etc/default/spfmilter DAEMON_OPTS="" SOCKET="inet:54321@localhost" # listen just on loopback on port 54321Save the file, and restart spfmilter
/etc/init.d/spfmilter restartNow 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 (,).
/etc/postfix/main.cf smtpd_milters = inet:localhost:54321 non_smtpd_milters = inet:localhost:54321Restart postfix
/etc/init.d/postfix restartYou 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: NOQUEUE: milter-reject: \ MAIL from zebra732.startdedicated.com[188.8.131.52]: 550 5.7.1 rejected by spfmilter; \ from=