Greylisting
This article will show you how I am using PF (the Packet Filter from the OpenBSD project) and spamd (also from OpenBSD) to implement greylisting and greatly reduce incoming spam. This method has nothing to do with any MTA, hence no configuration changes to the existing mail configuration is required.
Spamd and PF work together. PF will direct any known good clients directly to the mail server. It will send known bad clients to the tarpit, a slow-responding (1 byte per second) mail server. New clients, not known to be good or bad, will need to retry later.
Spamd is therefore not an email content analyzer; it does not actually examine the email payload. Spamd sits in front of your real mail server and listens for SMTP conversations. It's a good complement to email content analyzers like SpamAssassin. I've already set up SpamAssassin on this server, and it may seem confusing at first as SpamAssassin has its own spamd. If we check on the server currently
ps awx | grep usr | grep spamd
315 ?? S 0:00.65 /usr/local/libexec/spamd -v -g
610 ?? Ss 0:02.13 /usr/bin/spamd -d -c -m 5 (perl)
The first process seen is OpenBSD's spamd, and the second process is SpamAssassin's spamd. Spamd is now available as a FreeBSD port, so installation is straightforward:
cd /usr/ports/mail/spamd
make install clean
Now I'll add three entries to /etc/rc.conf:
pfspamd_enable="YES"
pfspamd_flags="-v -g"
pfspamlogd_enable="YES"
We'll log to /var/log/spamd.log (although I never check it):
touch /var/log/spamd.log
Edit /etc/syslog.conf and add
!spamd
*.* /var/log/spamd.log
To use spamd's greylisting features, you need to have a file descriptor file system /dev/fd/. You do this by adding the following line to your /etc/fstab:
fdescfs /dev/fd fdescfs rw 0 0
To ensure you have the latest versions of the spam blacklists, refresh them each day with a line in /etc/crontab:
11 1 * * * /usr/local/sbin/spamd-setup
Choose any random time you lke here, or update hourly if you prefer. Now we need to set up our spamd.conf - make a copy by:
cp /usr/local/etc/spamd.conf.sample /usr/local/etc/spamd.conf
Edit /usr/local/etc/spamd.conf to your liking (man spamd.conf for full details). A short example could be like:
all:\
:spews1:spews2:
# Mirrored from http://www.spews.org/spews_list_level1.txt
spews1:\
:black:\
:msg="SPAM. Your address %A is in the spews level 1 database\n\
See http://www.spews.org/ask.cgi?x=%A for more details":\
:method=http:\
:file=www.openbsd.org/spamd/spews_list_level1.txt.gz:
# Mirrored from http://www.spews.org/spews_list_level2.txt
spews2:\
:black:\
:msg="SPAM. Your address %A is in the spews level 2 database\n\
See http://www.spews.org/ask.cgi?x=%A for more details":\
:method=http:\
:file=www.openbsd.org/spamd/spews_list_level2.txt.gz:
Now to add our PF rules to /etc/pf.rules. First we create our tables:
table <spamd> persist
table <spamd-white> persist
table <whitelist> persist file "/etc/pf-files/whitelist"
The
Now we redirect according to our desired rules.
rdr pass inet proto tcp from <spamd-white> to $SERVER port smtp -> 127.0.0.1 port smtp
rdr pass inet proto tcp from <spamd> to $SERVER port smtp -> 127.0.0.1 port spamd
rdr pass inet proto tcp from !<whitelist> to $SERVER port smtp -> 127.0.0.1 port spamd
In our filtering rules, we also now add:
# for spamlogd to update the whitelists
# no need to log static whitelist
pass in quick on $IF inet proto tcp from <whitelist> to $SERVER port smtp flags S/SA synproxy state
pass in log quick on $IF inet proto tcp from <spamd-white> to $SERVER port smtp flags S/SA synproxy state
pass out log quick on $IF inet proto tcp from $SERVER to any port smtp flags S/SA synproxy state
Now all we have to do is reboot the server, and when it's back up, simply run:
/usr/local/sbin/spamd-setup
and we should be in business.
Allowing some time to run, we can later check who's been caught, using the spamdb utility:
spamdb
GREY|58.140.171.237|<cmcneyjbsj@freshjalebi.com>|<sales@hotwoks.com>|1179180221|1179194621|1179194621|1|0
GREY|64.135.240.109|<tonbodyguard@playcenters.com>|<sales@hotwoks.com>|1179180217|1179194617|1179194617|1|0
WHITE|88.204.186.231|||1179117711|1179128181|1182238590|2|0
SPAMTRAP|<none@hotwoks.com>
If you're wondering about the last entry (the SPAMTRAP one), I added this myself as the email address is non-existent, and if I 'hide' this in my webpages, some spambot will pick it up and start spamming. It can then be blocked of course. This is called greytrapping. To add email addresses like this, simply do:
spamdb -T -a "<sillyname@yourdomain.com>"
The GREY entries have only been seen once, so are still blocked, the WHITE entry has made it, and has been seen twice (the second-last number field in the output from spamdb).
Since we're doing greylisting, any greylisted host who attempts to mail to the destination address of sillyname@yourdomain.com would be blacklisted for 24 hours. These machines then show up in the spamd database as TRAPPED entries for the next 24 hours; i.e.:
spamdb | grep TRAPPED
TRAPPED|121.72.247.183|1179294878
TRAPPED|124.104.20.182|1179315355
TRAPPED|124.163.255.22|1179286582

