I am in the unfortunate situation of owning and using a decade-old domain that's only three letters long. As far as spammers go, this seems to be ideal territory. For the past year or so, this domain has wound up as a wildcard domain on a spambot network. This means that my sole mailserver gets somewhere between 500,000 and 800,000 attempted spams every day -- to nonexistent accounts. This load comes to about 10 emails a second, 24/7/365.
One of the many nefarious techniques used by spammers is to cull usernames from many domains, then attempt to send mail to those usernames at other domains, hoping that those accounts also exist there. In my case, there are only about 25 legitimate email accounts, but looking at my mail logs, you'd think that there were hundreds of thousands of users getting mail at my domain. Just dealing with the "user unknown" bounces resulted in sendmail using over 30% of the system resources on a constant basis. The mail path through the server passed all email to MIMEDefang, which calls SpamAssassin and ClamAV for spam and virus filtering, and the sheer volume was overwhelming the server. Something had to be done.
First, I started by implementing greylisting on all mail coming into the server. Greylisting is a relatively new technique, and fairly draconian, but is also very effective. In a nutshell, all email is initially refused with an SMTP 451 "Please retry later" error response to any remote MTA trying to deliver email. A legitimate mailserver will do just that. Spammers don't, however, since retrying thousands and thousands of failed messages isn't worthwhile to them. So, any email sent to the server is delayed anywhere from 30 minutes to several hours, depending on the configuration of the sender's mailserver. Once the message is resent, it is accepted and routed appropriately. This is implemented as a sendmail milter called relaydelay. When a unique sender is seen, a record is added to a MySQL database with an insert and expiration timestamp, and catalogued as a tuple consisting of sender address, recipient address, and MTA relay IP address. If a tuple is seen again, the expiration is pushed back 45 days, and the mail is accepted. Further contact from that tuple is passed through with no delay. The 45 day counter starts over if another email is seen from that person within that timeframe.
After running the stock relaydelay 0.04 code for a day or so, I noted that I really needed to be able to whitelist and blacklist based on sender domain. Relaydelay can whitelist relay IP addresses and recipients, but not wildcard sender domains. I wrote a patch to the milter that implements sender domain white/blacklisting, and have contributed it back to the project. This patch is to be applied against a stock relaydelay-0.04 tree, and incorporates Martin Walker's daemonizing patch.
Armed with these tools, the spam that actually makes it to my mailbox stopped almost completely. There are a few spammers out there that do resend following a 451, but they are very small in number and easily blacklisted. In fact, it was so effective that I wrote an auto-mailer script from another domain that sends an email every 30 minutes so that I could quickly verify that the email pathing was still working, since my mailbox got very quiet, very quickly.
All this is great news, since it's all but eliminated my spam load, and has the side effect of reducing the load generated by MIMEDefang/SpamAssassin/ClamAV mail filtering on the server... but the database load went through the roof.
Those hundreds of thousands of dictionary spams seen daily all required another record in the MySQL database, thus driving the database size to well over 60MB on a daily basis. Running database maintenance scripts nightly would drop the database size to only a few MB, but by 8PM, every email generated a SELECT on a 50-60MB database, and I was more or less back where I started. The scope of the distributed spam attack that I've been subjected to is immense. thousands and thousands of compromised Windows systems on residential cable and DSL connections were hitting the server constantly, and while unsuccessful, they would simply keep trying with different sender and recipient addresses.
So, I wrote another extension to relaydelay. Now, if a remote MTA sends over 15 messages without retrying, then attempts to send more email over 100 minutes later, the relaydelay milter will add a record to another table in the database consisting of the relay IP, hostname, and various timestamps, and an generate a local ipfw firewall rule on the mailserver to permanently block all connections on TCP/25 from that IP address. When I first wrote this patch and began testing it, the blockedrelays database and firewall rules were being generated at a rate of about 10 every minute. At the moment, there are over 14,000 blocked relays -- and over 14,000 ipfw rules -- and the mail volume has dropped to about 40,000 every day. In the past four days, over 2 million connections were denied from remote MTAs, and new rules are being generated every few minutes. The more time passes, less and less spurious messages are seen, and the mail load on the server has dropped dramatically. Should the server be rebooted, a companion perl script pulls the blocked relay IP addresses from the database and recreates the ipfw rules.
A perusal of the blockedrelays database shows thousands and thousands of reverse DNS names that correspond to cable and DSL providers. ComCast cable subscribers, or example, appear over 150 times. I haven't yet made the auto-shunning patch available to the public, since I need to be sure that it's as accurate as possible, but I have sent it to a few relaydelay users upon request.
Of course there are caveats to my approach. For instance, securityfocus.com fell into the blockedrelays table and was shunned, but this was due to the fact that they apparently pool their mailqueue amongst several servers, so the tuple never matched twice. This was easily dealt with by whitelisting securityfocus.com. Also, poorly configured or seriously overworked mail relays may not retry messages within the four-hour grace period, and will be further delayed, but these instances have proved exceedingly rare. The one regrettable side effect is that time-sensitive email sent from a new sender can take 30 minutes or more to appear, but adding a whitelist for their domain or address before they send can alleviate the wait.
Now for the first time in years, I have a spotless inbox, and a mailserver that's significantly less busy. Until legitimate legislation is adopted that actually has an effect on spammers of this nature, or the security flaws in Windows are miraculously fixed, intrusive mail filtering schemes such as this are going to be required. This battle might be won at the moment -- at least for me -- but the war is far from over.