Stopping Spam at the Door with Exim
I'm sure I'm not the only person who is getting fed up with masses of spam landing in their inbox each day. My annoyance has lead me to do something about it. Rather amazingly, I have managed to reduce spam to nearly nothing, about a 95% reduction! In this article I will discuss the pros and cons of the various spam reduction methods. This article of only for people who know the SMTP protocol, and arn't afraid to create custom packages. If you're looking for a 5 minute fix for spam, this certainly isn't for you. If you have any problems understanding anything here, please don't contact me, instead, stop running a mail server, you clearly arn't smart enough to do so!
Untill last week, I was using a program called Active Spam Killer (ASK). This software stops spam completly. ASK does not analyise the contents of emails, but instead uses a challenge based authentication method. This means, when someone emails you, a confirmation message is sent to them. This message simply asks them to reply. Unless the sender replys to this confirmation mail, thier origional mail is stored in a queue. When they do reply, thier email address is added to a whilelist, and the mail is finally delivered to your mailbox. The next time you are emailed from that person, the message is delivered as normal, as the sender is in your whitelist. This method is very effective, but it is a little annoying for the people trying to email you. and some people are so stupid they don't understand the message saying something along the lines of 'YOU MUST REPLY TO THIS MESSAGE IF YOU WANT ME TO GET YOUR MAIL'. You might not beleive me, but it's true, some people really don't understand that.
Although ASK was doing a good job, it was installed just for one user, not system wide. Also, it didn't stop the emails from getting into my mail queue, it just stopped them hitting my inbox. I wanted something that would work across the whole system, and stop mails even being accepted by my server. To do this, I use Exim with it's ACL system and it's local_scan functionality.
Using Exim to Prevent Spam
Exim ACLs provide a system to deny or accept messages based on conditions.
I have found that virus's and spamming mail servers often send a load of rubbish in thier HELO. It is possible to make sure that the hostname provided actually matches the connecting host, but I find that this stops valid mail. The following ACLs will ensure that an IP address isn't given, and the hostname contains atleast one dot.
check_helo:
deny message = Your server announcement ($sender_helo_name) \
is a single word rather than a FQDN. This is \
in breach of RFC2821
condition = ${if match {$sender_helo_name} \
{\.} {no}{yes}}
deny message = Your server announces itself \
($sender_helo_name) with a plain \
IP address which is in breach of RFC2821.
condition = ${if match {$sender_helo_name}\
{^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\$}\
{yes}{no}}
accept
The following ACL can be used to deny VRFY commands with a specific error message.
check_vrfy:
deny message = VRFY not allowed - it can help spammers. (but \
some silly clients use it still) Attempt has \
been logged
The ACL for checking the recipient address can be used to check the syntax of the address, and also to check the address against some DSN lists. The following will most likly need changing to suit your needs, but this is from my setup.
check_recipient:
accept hosts = :
deny local_parts = ^.*[@%!/|]
deny message = Your host is listed in : .
log_message = found in :
dnslists = relays.ordb.org:list.dsbl.org:bl.spamcop.net
accept domains = +local_domains
endpass
message = No Such User Here.
verify = recipient
accept hosts = +relay_hosts
deny message = relay not permitted
This ACL is run after the DATA command, so it can be used to check the contents of the email
check_message: require verify = header_syntax require verify = header_sender accept senders = !: require verify = header_sender accept
If you are unsure as to what any of these ACLs do, or how to set exim up to use them, take a look at the exim manual which is online at http://www.exim.org.
Exim has a wonderful feature called local_scan. This allows you to write some C code that gets compiled into Exim allowing the message to be scanned before it is accepted. I have created a local_scan.c that passes a file handle of the mail, and the mail headers to a perl script. This perl script can then be used to check the mail. I personally virus scan messages, and pass them to sophie for virus scanning at this stage. This allows me to reject messages that look like spam, or contain a virus before they even make thier way onto my mail server.
If you want to go down this route, I'm going to assume you can read source code, so I'll simply include the local_scan.c, and my local_scan.pl file. All you need to do is compile your exim with my local_scan.c, and place the local_scan.pl in /etc/exim. You'll probably want to hack about with local_scan.pl to suit your needs.
4th December 2004 I no longer use my custom local_scan code, but instead use exiscan. This can achive almost exactly the same thing.
This ia a link to my Exim perl module that provides the header_add function, and the return codes used in my local_scan.pl.
Conclusion
In conclusion, it's not one method that will stop spam, it's a combination of lots. The only way we will see an end to spam isn't though laws and reguations, as that will only stop the law obiding people, what we need is a change in how emails are sent and delivered. This being said, it is important as server administrators, that we everything we can to prevent the spread of spam, and to stop our users getting bogged down with hundreds of spams.
Credits
Thanks greatly to Theo. Theo gave me some of those wonderful ACLs and the idea before using the perl local_scan stuff. Also thanks to Richard Baker who did most of the work on the local_scan.c that I hacked about and used.