Skip to content

Mail Server, Spam Blocking and firewalls

Dear Reader,

You may or may not know that I run a web hosting service and Internet design company in all of my spare time. This affords me the opportunity to do some interesting things like have long discussions on forums with other admins about the relative value to blocking spam at the firewall .vs the MTA. Thanks to Jeff Lasman those of us who use DirectAdmin and exim have a new SPAM fighting tool, the SpamBlocker configuration file for exim. It’s a great piece of work. If you run exim, even if you don’t run DirectAdmin, it’s worth a read just to see all the good ideas in one place.

Jeff just recently released version 2.0 of the file and while discussing it, our attention turned to blocking spam at the firewall instead of at the MTA. Obviously, it takes less resources but since a lot of spam comes from dynamic IP addresses (evil zombies) you don’t want to block those IP from your server forever or eventually no-one will be able to get to your site. Also, there are several problems that I’ve yet to overcome technically, not the least of which being that exim runs as a non-privileged user (as it should) but this precludes it from executing iptables. So, for the moment, I’m left with a less than optimal but perfectly workable solution.

1 – You need Jeff’s SpamBlocker conf file for exim. If you don’t run DirectAdmin, you will have to modify it to suit your needs but it’s well worth the effort. If however, you don’t want to start from scratch with a new conf file, this idea will work with just about any exim.conf file for 4.50 or better. (it may work with any version of exim 4.x but I’ve not tested it.)

It’s important at this point to say that before you implement this make sure exim is working 100% and then back up your conf file. if nothing else, email it to yourself. It gives you a backup AND you know it’s working! :)

2 – Ok, so you have a working exim.conf file. Now let’s tinker with it. Somewhere in your acl_smtp_rcpt (in SpamBlocker it’s the check_recipient ACL) you need to put the following:

# Blatantly stolen from
# Many props and thanks guys.
# If they added themselves to the file below, let's block them for Dict Scan!!!
deny  message       = Blocked because your address is being used for a dictionary attack.
hosts         = /etc/exim_deny
!hosts         = +relay_hosts
!authenticated = *
delay         = 150s
log_message   = Blocked because of dictionary scan.

deny  message       = Max $rcpt_fail_count failed recipients allowed
condition     = ${if > {${eval:$rcpt_fail_count}}{2}{yes}{no}}
condition     = ${run{/etc/ $sender_host_address}{1}{1}}
!hosts        = +relay_hosts
delay         = ${eval: ($rcpt_fail_count) * 30}s
log_message   = Dictionary scan! $rcpt_fail_count failed recipient attempts

If you are using SpamBlocker like me, consider putting it below:

# accept mail to hostmaster in any local domain, regardless of source
accept  local_parts = hostmaster
domains     =+local_domains

3 – Ok, save that. Now, download and save it in your /etc dir. Make sure it is executable by the user account that your exim runs under.

4 – create the file /etc/exim_deny and make sure that it is writable by the account that your exim runs under.

5 – Restart exim

At this point you should have a working solution. There are a couple of things you might want to do.

First, as Jeff pointed out, neither executables nor storage files should be in your /etc. Hey, I didn’t write it and I’ve been too lazy to change it up to this point. But he’s right and you should move the executable somewhere appropriate and the exim_deny file to somewhere in your /var directory.

Second, if you don’t watch it, exim_deny is just going to keep growing and growing. Since I hate manually editing files as much as the next guy I wrote a little php script to do it for me.

Download and save on your server as a php file. Make sure the reference to the php interpreter is correct and if you move the exim_deny file, change it here too. Now, after you run it a few times to make sure it works the way you want it to, drop it in your cron and forget it. Run it as often as you like. Hell, fire up PuTTY and run it in the middle of the day if you get bored. FWIW, I run it every night about 3 AM. (and if my boss is reading this, as far as you know I don’t run it in the middle of the day because as far as you know I’m not bored.) :)

That’s it. Like I said, it’s not a perfect solution. Blocking the IP addresses at the firewall is a much more efficient solution. Especially if you have a busy server that gets attacked a lot. But I present it here for you because it worked for me. I encourage you to drop me a line with any improvements. I’ll make sure and share them.

Until next time,