Most approaches to filtering spam don't work well when you're only getting a spam or two from each IP that connects to your server. For instance, one very nice way of catching spammers is by placing a few honeypots around and then blocking whatever IP sends mail to them. Unfortunately the kind of spam I'm getting is really dumb, in the form of messages to addresses that _don't_ exist. This causes the message to bounce back to the faked originating address. I say it is dumb because the person who actually receives the bounce gets it is "error" form, not as the clean original message, and thus will more than likely not read it. Even if they do, they'll be pretty sure that they didn't send the message, and will not click on the spam link that they supposedly sent someone else. SIGH!
Anyway, some pathetic spammer with a fairly big botnet thinks it's a great idea and decided to bounce some of his trash off my server. I'd really like to block that spam _before_ it gets delivered to my SMTP server (Exim in my case--yes it's very l33t). That being the case I created a tiny Perl script to tail the Exim log files and block access to port 25 from any IP that sent me spam. The idea was to prevent any further spam from that IP from even connecting to my box.
That worked fine and dandy, with only a small problem (or two). Very few IPs returned to spam me again. As I said, this guy's botnet is quite large, and many of his zombies have dialup or dynamic IP DSL/cable. The other problem is that there are just _a lot_ of them. A single day of logging resulted in over 15,000 IPs added to my firewall.
OK, let's go to plan B. Lots of other people are getting this spam, right? Let's see what they're doing about it! Turn out that a very efficient way of dealing with this type of bot is by allowing a pool of servers to rat on the IPs that are delivering spam. That way other servers can block their spam _before_ it's delivered. I guess this is how Vipul's Razor works, but I've never gotten to install it. I just used the lazy approach: filter whatever everyone else is filtering.
Most people don't worry that much about spam because they get only a few messages a day. ISPs and large companies, however, _do_ mind. And so a few "central" facilities for consolidating these spam sources were born. To distribute the data, a very clever approach is used: DNS. The fact that everyone that uses the Internet already uses DNS, and that it is distributed and has built-in caching, and deals with IPs, make it the prime candidate for the job. All that has to be done is to create a dummy (non-authoritative) reverse zone, and then clients can query the database using W.Z.Y.X.dnsbl.domain.tld to check if IP X.Y.Z.W is blacklisted. BTW "DNSBL" simply means DNS Block (or Black) List.
This all sounds quite complicated, but to implement it with Exim takes only a few lines. Exim4 supports ACLs (Access Control Lists), so all you have to do is add an ACL entry:
deny hosts = !+relay_from_hosts
message = $sender_host_address is listed \
dnslists = dnsbl.njabl.org : \
bl.spamcop.net : \
dnsbl.sorbs.net : \
blackholes.five-ten-sg.com : \
cbl.abuseat.org : \
psbl.surriel.com : \
I chose to not check for spam from anything in my relay_from_hosts variable (for obvious reasons). You basically choose a message to use when rejecting (and logging) an attempt of spam delivery, and specify a list of domains to be used for the reverse mapping checks. Normally these DNS servers will return NXDOMAIN for regular IPs, or 127.0.0.2 for known spam sources.
So there you have it. I came up with my list of DNSBL sources by searching the excelent OpenRBL (a kind of DNSBL meta-search) for the spam sources that reached my box.
Also note that on of my DNSBL sources is psbl.surriel.com. This is Rik van Riel's (of Linux Kernel hacking fame) site, and is powered by Spamikaze, a tool that I plan to run on one of my boxes soon. The plan is to have my own DNSBL based on the spam that still gets through to my box.
I'll end this entry with a big "THANKS!" to all the projects mentioned (this is all free, folks) and look forward to paying them back with some pizza and beer in the future.