There are many different methods of securing a publicly accessible server, and one of the best things a system administrator can do is use fail2ban to dynamically block potential attackers before they can do any damage.

First, you will want to install Fail2ban, so head over to Fail2Ban.org and follow their instructions for installing on your distribution. On CentOS or RedHat, you will need to first install the EPEL repository. After doing so, fail2ban can be installed with the yum command yum install fail2ban. That takes care of the installation!

Once you have Fail2Ban installed, you can start configuring it! One of the problems that I run into with Fail2Ban is that it will try to load all the firewall rules too fast, resulting in errors like this:
iptables -I INPUT -p all -j fail2ban-w00tw00t returned 400
You may also get some 100 or 200 errors as well. Well, the fix for this is easy enough (and hopefully it will be incorporated into upcoming versions; as of version 0.8.4 is is not). Simply edit the file /usr/bin/fail2ban-client and add the line time.sleep(0.1) into the __processCmd function. This is added around line #145. The first few lines of the function should look like this:

def __processCmd(self, cmd, showRet = True):
    beautifier = Beautifier()
    for c in cmd:
        time.sleep(0.1)
        beautifier.setInputCmd(c)
        try:

So, now that we have a working Fail2Ban setup, we can start configuring some rules!

First, take a look at /etc/fail2ban/fail2ban.conf. This lets us specify some log options. The only one that I am really concerned about is the logtarget, which I like to set to /var/log/fail2ban.log.

Next, let us look at the /etc/fail2ban/jail.conf file. Here you will want to configure your list of ignore IP’s, which should include localhost, and your trusted machine(s) or subnet (ex: ignoreip = 127.0.0.1 192.168.0.0/24 8.8.8.8). You can also adjust the bantime, findtime, and maxretry options, all of which are explained within the file.

Next you can pick what jails to run, and override any global settings with specific settings set here. Spend some time reading through the different jail configurations to get an idea for how to set yours up. I’m always a little more paranoid about security; I don’t want any cats in my dogghouse, so I will usually completely ban any user that fits one of my rules. You could optionally just ban them from using the service they are attempting to exploit, if you wish.

Lets take a look at a jail configuration that I wrote myself.

[dns-root]
enabled  = true
filter   = dns-root
action   = iptables-allports[name=DNS-ROOT]
           sendmail-whois[name=dns-root, dest=jerp@herpandderp.com, sender=fail2ban@myserver.com]
logpath  = /var/named/chroot/var/log/bind.log
maxretry = 2
bantime  = 86400

One of my nameservers was getting a large number of NS lookup requests for the root domains. Well, our server isn’t authoritative for the root zone, so we respond with a REFUSED notice, however this didn’t keep the requests from coming. At first I thought that it was some sort of lame DOS attack against one of my nameservers, but after investigation I found that this was likely a Root DNS Amplification Attack against Facebook! I would get approximately one request per minute for the root NS records, sending out one REFUSED response per minute to an IP address owned by Facebook. In order to combat these annoyances, I created the [dns-root] jail for Fail2Ban.

Lets take a look at what each setting in this jail does. First, the enabled line dictates whether or not the jail is active. Next, the filter line specifies the name of the filter that will be used to match undesired behavior. The action line in this case says to run the iptables-allports action, inserting an iptables rule into the chain named DNS-ROOT, which will drop traffic from the banned host on all ports. Optionally, you can select to only have specific ports dropped, instead of banning the host from your entire server. The sendmail-whois line lets us send an email, with whois inforation about the banned host, to whoever you like. Finally the logpath specifies the actual log to be checked against, and the maxretry along with the bantime values will override the global variables you specified earlier in that file.

Next, take a look at the matching filter. After removing some extra comments, we are left with this:

# Fail2Ban DNS-ROOT configuration file

[Definition]
failregex = ^.* security: info: client #.*: query \(cache\) './(NS|A|AAAA|MX|CNAME)/IN' denied

ignoreregex =

What we have are two variables. The first is failregex, which is a regex formatted statement to match denied root zone lookup lines in our log files. The next variable, ignoreregex, lets us specify something to search for, which will cause a matched line to be ignored. Basically, if the failregex line is matched, the host is banned. If both lines are matched, the host is not banned.

Now, once you have everything configured, you should be able to set the service to start at boot with the chkconfig fail2ban on command, and immediately make the service start with the service fail2ban start command.

Now you can finally have some piece of mind, knowing that those pesky internet cats wont be able to get into your dogghouse and steal your bone!

If you are interested in creating your own rules, check out Regexpal.com for help in writing and debugging regex.