Home PHP and MySQL CodeCode PoetryPoetry Articles I've writtenArticles My ResumeResume PicturesPictures Left Circle StoriesCircle Blog Circle TreoPix
Me
Cal Evans . Com - The life, love, code, and bad poetry of Cal Evans.
Latest Additions:



Exim_Deny_Manager


Current Version 2.0
Copyright 2006 Cal Evans
License GPL 2.0

UPDATE: 02/03/2006 - Cal

I've made major changes to the system so please pay attention if you are upgrading.


This all started as an interesting conversation over on the DirectAdmin forum. We have a great exim expert over there, Jeff Lasman. He wrote the exim.conf file I (and most of us using DirectAdmin) use. It has some great spam blocking rules and is very configurable.

One of the few things it didn't do is handle dictionary attacks though. One day, while watching my server get hammered in an attack, I went out and found some code over at http://www.configserver.com/free/eximdeny.html that did a lot of what I wanted. it had a couple of problems, the files were in an inconvenient place and basically the file just built and built until, if you didn't do something about it, you were blocking a good chunk of the net.

So I set out to solve those problems. Along the way, I shared the idea on the DirectAdmin forums. It seems that other people were interested in this idea as well. But Jeff pointed out that just because exim CAN do this work, doesn't mean it's the best place to do it. He has a point. Exim can quickly bog down on a large server if it's scanning every mail coming in to make sure it's not coming from a blocked IP address. besides, that's what we have firewalls for. So when I decided it needed a re-write, I wanted to incorporate this feedback in. Thus exim_deny_manager.php was born. exim_deny_manager allows the mail administrator to immediately block IP addresses when an attack starts. At specific intervals, he can run EDM to move the IPs exim has collected into a firewall deny file like APFs deny_hosts.rules. Then restarting the firewall makes blocking those IP addresses the problem of the firewall and not exim. To me this is the best of both worlds. Here's how I make it work.

Now own with the technique. To block email from specific IP addresses using Exim, you need to do the following.

1 - You need the 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.

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
# http://www.configserver.com/free/eximdeny.html
# 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         = /var/tmp/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{/usr/local/bin/dictscan.pl $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 dictscan.pl and save it in your /usr/bin/local dir. Make sure it is executable by the user account that your exim runs under.

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

5 - Restart exim

6 - 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, exim_deny_manager.php 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.

I recomend 1 of 2 techniques for placing this in a cron.

1: Everything all at once.
At specific intervals, every hour, every 3 hours, whatever you like run this.
/path/to/exim_deny_manager.php -m -rf ; apf --restart
That executes a (-m)move and a (-rf)remove expired from firewall. Those 2 will keep a running 24 hours of IP addresses being blocked.


2: Split
Every so often once an hour, once every 3 hours it really depends on how many attacks you get and how painful it is to restart your firewall; execute the following:
/path/to/exim_deny_manager.php -m ; apf --restart
This moves all the IPs that exim has collected into the firewall and restarts your firewall.

Then once a night execute the following:
/path/to/exim_deny_manager.php -rf -s 172800 ; apf --restart
This removes any IP address older than 48 hors from your list and restarts your firewall.

The second method is the one I am currently using.

That's it. I hope you like it and it helps to protect your server from bad guys.




Spacer
gunther logo  Last modified: Wed, 8 February 2006 (09:03:38 AM)