You are here: Home Tech Stop spam with spamd and pf

Stop spam with spamd and pf

by Chris Shenton last modified Sep 23, 2008 03:36 PM
Turned out to be remarkably easy and effective. Wish I'd done it sooner.


I've tried a bunch of anti-spam techniques including DCC, qmail-spamd, CRM114 but found them a bit painful to set up, ineffective, or require senders to do someting. After switching from qmail to postfix recently, I lost all my anti-spam trickery and finally got fed up. 


A colleague had reported great succes stopping spam -- to the point that he'd happily tell me that he got a spam one day.  His approach was similar to one described on the FreeBSD Diary. Both use OpenBSD's pf packet filter and spamd spam deferral filter, but both descriptions incorporated a lot more functionality than I needed just to cut down spam.

The idea is that when a host connects to your mail system, pf sees if its in your whitelist. If not, it sends it to the spamd. If it's new to the spamd, it slows the connection then returns a temporary error, signling to compliant mailers that they should retry later; if it returns after a sane amount of time (e.g., 25 minute default) and before an expiration time (default 36 days), then it whitelists the sending host and lets the mail through.  It can also subscribe to blacklists which block the mail, period.

It may not be 100% fool-proof, but it seems very, very good.  If a spam sender follows the SMTP rules that legitimate senders use, sending once, and waiting a half hour before trying again, they can get their mail through. But most spammers use bots running on compromised Windows machines which don't have sophisticated outbound mail queue mechanisms. This stops the drive-by-shooting style of spam zombie. Nor does it prevent spam mail which was accepted by a mailing list that your on: the mailing list is a legitimate sender, it's just re-transmitting the spam.

For what it's worth, I'm using FreeBSD-7 and Postfix. The mailer doesn't matter but your OS will have to support pf and spamd.


Build spamd, answering 'yes' to let it install the required user, group, and service/port mapping:

cd /usr/ports/mail/spamd
make install clean

Copy the supplied /usr/local/etc/spamd/spamd.conf.sample to spamd.conf. I left everything alone, the default "greylist" behavior seems fine to me.

You'll need to add a "file descriptor file system" so spamd can greylist senders; add the following to /etc/fstab:

fdescfs /dev/fd fdescfs rw 0 0

then mount it manually so we don't have to reboot:

mount /dev/fd


I took the FreeBSD Diary's suggestion to use a nonstandard location for the rules file, in case mergemaster might want to munge it. Edit /etc/pf.rules:

table <spamd-white> persist
no rdr   inet proto tcp from <spamd-white> to any port smtp
rdr pass inet proto tcp from any           to any port smtp -> port spamd

This sends any hosts not in the spamd whitelist to spamd.


Edit the /etc/rc.conf so they start at boot; I like the verbose flag for spamd, with syslog set to log INFO and above.

pf_rules="/etc/pf.rules"        #prevent MergeMaster from trashing default pf.conf                                                             
obspamd_flags="-v"              #log who at INFO, body at DEBUG                                                                                

I added a couple lines to /etc/syslog.conf so that spamd could log verbosely (-v) into its own file, showing me From/To info at the INFO level, but suppressing the body sent at the DEBUG level. Remember to touch the file to create it then restart syslogd.

daemon.err;daemon.warn;      /var/log/spamd

Start them up

Unless you've compiled 'pf' into your kernel, you'll need to load it.  The kldload man page suggests this is done automatically at boot time, but you don't need to reboot to turn this on.

/usr/local/etc/rc.d/obspamd start
/usr/local/etc/rc.d/obspamlogd start

kldload pf
pfctl -e
pfctl -f /etc/pf.rules
/etc/rc.d/pf start
/etc/rc.d/pflog start

Check it out

Watching /var/log/spamd is informative, with the -v flag showing sending addresses getting grey listed.

Talk to your SMTP port. If this is the first time you've connected, pf will direct you to spamd and you can see it stuttering, then rejecting you if you type a normal SMTP session at it. The greeting and prompts are funny. Sadly I can't show the stuttering here, but it takes about 10 seconds for it to give the greeting.

220 ESMTP spamd IP-based SPAM blocker; Tue Sep 23 15:03:54 2008
250 Hello, spam sender. Pleased to be wasting your time.
250 You are about to try to deliver spam. Your time will be spent, for nothing.
250 This is hurting you more than it is hurting me.
451 Temporary failure, please try again later.
Connection closed by foreign host.

 You can also see the status of your spamd white/gray/black database with:


Over time -- after the 25 minute greylist window -- you should start to see legitimate sending hosts get marked WHITE intstead of GREY. And your mail should start coming in again, after being blocked by spamd for that time. 

But now it should be free of spam, or almost free of spam.

But wait, there's more!

You should use the "spamd-setup" command to load spamd with the blacklists configured in /usr/local/etc/spamd/spamd.conf.

You can also add spamtrap addresses that spammers send to.

You can drastically increase the stuttering and tarpit timing to waste sender's resources, delaying their attacks on others.



Share this: