Spam filtering with OpenBSD and making spamming a little harder
Spam is the most annoying thing I have to deal with every day on my servers. Only 3-4 spams make it daily all the way to my inbox, but I got tired of thinking about all the energy wasted by sysadmins blocking unwanted messages, so I decided to do something about it. It is too easy and cheap for spammers to send unwanted messages via email right now, and they might even make money from it. Recipients on the other hand must bear the cost of managing incoming spams. To make spamming a little more difficult, I set up tarpits to increase usage of spammers' resources.
Whenever a bot is busy wasting time on one of my tarpits, it is not sending spam. Spammers get payed by volume and every time someone slows them down they are losing revenue. On my spamtrap machine, by holding connections open for as long as possible, I am wasting more than 720 hours (30 hours per day) worth of spammer connection time. The spamtrap also helps me to build my blacklist and therefore improves my spam filter.
To annoy the spammers I use spamd. Spamd is a lightweight spam-deferral daemon. Spamd is a fake SMTP-like daemon designed to work in conjunction with pf(4). It runs on any machine with OpenBSD, NetBSD, FreeBSD or any BSD Like system.
Spamd works by sitting between the sender and the MTA, blocking all the undesired connections before they reach the SMTP server. Spamd offers features such as Blacklisting, Tarpitting, Greylisting and SpamTrapping. It doesn't replace a mail filter but greatly limits the number of connections reaching the real mail server.
In this post I am going to explain how I have configured spamd on my network. Once the sender IP address has been cleared by spamd, the mail is then handled by my real SMTP server. Please refer to your documentation to setup an SMTP server.
Spamtrap and tarpit, how it works
I am luckyto have 2 machines in 2 different locations, but this configuration can also be done with one machine or two machines in the same location. The machine in Location 1 is hosting my MTA. The MX record for my domain name points to that machine. This machine also runs spamd to greylist all the incoming SMTP connections, before they are sent to my SMTP server.
The machine in Location 2 is a spamtrap and doesn't handle any real email. I have a few domain names that were popular a long time ago but that haven't beeng in use for a dozen of years. In theory ---in a world without spammers--- these domain names shouldn't receive any email. Unfortunately spam bots are sending an average of 25,000 emails per hour to these domain names. Once a spammer connects to that machine its connection is slowed down to one character per second, holding the connection for as long as possible. Its IP address is also put in a blacklist. That blacklist is then synchronized with the main mail server. The main mail server will benefit from the bad IP addresses learned by the spamtrap.
The main mail server is a simple rack mount PC hosting several services. It is noteworthy that the spamtrap is running on a small 1GHz machine with 256MB of ram and no disk, (see picture on the right). That box only consumes 14 Watts of energy and can gather many spambot IP addresses with little impact on your electric bill. The operating system is an embedded version of OpenBSD. The system is booted from a 2GB flash. This machine is powerful enough to handle several hundred simultaneous connections from mail bots. While I am writing this post the spamd is handling 1600 simultaneous SMTP connections and I have enough resources to easily have 4 to 5 times more connections.
In this graph you can see the number of IP addresses trapped and blacklisted by the SMTP server.
Spamtrap and Tarpit configuration
The Location 1 runs spamd and exim on my main mail server.
If an SMTP server connects to the machine for the first time, pf
checks if the IP address is in the whitelist. If the IP address of the
sender is whitelisted, pf sends the connection directly to exim for
normal email processing. If the address is not in the whitelist, the
connection is sent to spamd on the port
8025. Spamd emulates an SMTP
server, but cuts the connection with a temporary error (error 450),
forcing the sender to resend the mail later. The IP address is then
placed in the greylist. Next time the SMTP sever will connect to try
to send the same email, the IP address will be placed in the whitelist
and pf will let that connection go through and reach the SMTP server.
For more details on how greylists works, you can read the Wikipedia page.
Here is the part of my
/etc/pf.conf file that blocks the IP
addresses that are blacklisted, sends the new connections to spamd and
lets the whitelisted IP addresses go to the SMTP server.
# spamd-sync pass in quick log on $out_if inet proto udp from $spamtrap to $mainserver \ port spamd-sync # spamd tables definitions table <spamd-white> persist table <nospamd> persist file "/var/db/whitelist.txt" table <localtmp> persist table <localblack> persist file "/var/db/local-black.txt" # block all the ip addresses that are blacklisted block in quick log on $out_if proto tcp from <localtmp> to any port smtp block in quick log on $out_if proto tcp from <localblack> to any port smtp # Incoming connections that are whitelisted goes directly # to the smtp server pass in on $out_if proto tcp from <nospamd> to any port smtp pass in on $out_if proto tcp from <spamd-white> to any port smtp # send the new incoming connections to spamd pass in on $out_if proto tcp from any to any port smtp rdr-to 127.0.0.1 \ port spamd
On lines 2 to 3 you can see the rule allowing the incoming UDP spamd-sync connections from the machine in the Location 2. This allows the machine running the spamtrap to send the list of the IP addresses that have been blacklisted.
The following file is the configuration file for spamd
/etc/mail/spand.conf, containing my personal whitelist and personal
blacklist. I usually don't use blacklist found on the internet because
I don't trust them. Sometimes they are too restrictive or out of
date. The good lists are usually not free and are too expensive for a
personal use. I simply rely on the greylisting mechanism provided by
spamd and my own spamtrap to block the majority of the bots. I also
use SpamAssassin on the mail server to classify the spam for the
remaining emails that reach the server. The greylist blocks about 98%
of the illegitimate connection to my MTA.
# spamd(8) configuration file, read by spamd-setup(8). # See also spamd.conf(5). # # Configures lists for spamd(8). all:\ :override:localblack: override:\ :white:\ :method=file:\ :file=/var/db/override.txt: localblack:\ :black:\ :msg="SPAM. Your address %A appears to be in our local blacklist":\ :method=file:\ :file=/var/db/local-black.txt:
The following lines need to be added to your
to automatically start spamd at boot time.
spamd_flags="-5 -G8:4:864 -y xx.xx.xx.xx -S 16 -n \"Postfix (Debian/GNU)\"" spamlogd_flags="-i em0"
-5For blacklisted entries, return error code 550.
-G8:4:864passtime:greyexp:whiteexp Adjust greylisting timeouts.
-y xx.xx.xx.xxallow spamd receive synchronization messages from the spamtrap server
xx.xx.xx.xxshould be replaced by the IP address of the spamtrap machine.
-S 16Stutter at greylisted connections for 16 seconds
-n "Postfix (Debian/GNU)"Name shown in the SMTP banner. (I know... I am lying here)
Location 2 (Spamtrap)
The Location 2 runs on a tiny client described earlier in this post running an embedded version of OpenBSD. This machine does not handle any real email. All the emails coming to this machine are sent to expired domain names, and email addresses that have never existed.
OpenBSD's pf sends all the connections to the SMTP port to spamd
listening on its default port
8025. I could have spamd directly run
on the SMTP port, but this configuration allows me to change the pf
rules to do DoS mitigation in case of an attack. For example, in the
following rule I only accept 2000 connections at a rate of 50
connections per minutes (line 5). Once the threshold is reached the
ip address of the offender is placed in the
smtpforce for one hour.
table <smtpforce> persist pass in on $out_if inet proto tcp from any to ($out_if) port smtp \ flags S/SA synproxy state \ (max-src-conn 2000, max-src-conn-rate 50/60, \ overload <smtpforce> flush global) rdr-to lo0 port spamd
Don't forget to add the following line to your root crontab to expire
the IP addresses that are in the
smtpforce table after an hour.
0 * * * * /sbin/pfctl -t smtpforce -T expire 3600
The following lines from the file
/etc/rc.conf.local containing the
flags for starting spamd.
spamd_flags="-5 -c 1600 -h mytrap.com -l 127.0.0.1 \ -n 'Postfix (Debian/GNU)' -S 60 -Y yy.yy.yy.yy" spamlogd_flags="-i rl0"
-5For blacklisted entries, return error code 550. I could return an error 450, but I want to give a chance to a legitimate SMTP servers to unsubscribe this email address from its lists, or to a real person to get a bounce message as soon as possible.
-c 1600The maximum number of concurrent incoming connections.
-h mytrap.comThe hostname that is reported in the SMTP banner.
-l 127.0.0.1Specify the local address to which spamd is listening to.
-n "Postfix (Debian/GNU)"Name shown in the SMTP banner.
-S 60Stutter at greylisted connections for 60 seconds.
-Y yy.yy.yy.yyThis is the IP address of the machine to send the blacklist notifications.
The spamd configuration file located in
the following lines.
# all:\ ::
The most important file is the file
This file lists the domain names allowed to receive email from the
outside. All email sent to any other domain than the ones listed in
that file will be tarpitted and then blacklisted.
fred$ cat /etc/mail/spamd.alloweddomains randomfakedomain.com
All imcoming SMTP connections to that machine will be tarppited and their IP addresses will be blacklisted. The blacklisted IP addresses will be sent to my real SMTP server, allowing it to block spammers.
It is also important that you maintain a good whitelist. You'll need to create a whitelist containing the IP addresses of all the majors mail services such as yahoo, gmail, hotmail, etc. Since these services are also used by small spammers, you may end up completely blocking them. By whitelisting these big providers you ensure that their emails will be delivered without delay and they will be not get blocked.