Fail2Ban

In this post, I wanted to talk about fail2ban, and how you can use it for more than just blocking common SSH brute force login attempts. You see mention of this as a common defense for that, but since I access my servers from a static IP, I have strict port 22 iptable rules allowing certain IPs. I understand if you have dynamic IP or have the need to travel (and don’t have VPN) that this is not an option, and fail2ban is your ticket to protect yourself.
One thing that I’ve been working on over the years, is to lessen my server load and services from annoying requests. These requests will sap your server of resources and can drastically hamper it’s performance. Some great technique is to use Snort in conjunction with snortsam and the bleeding rule set. One set of rules will block spamhaus IPs for 72 hours. These rules are updated daily, so we can adapt with the changing spam IPs.
Why bother with this? Simple, this lessens the interaction of the mail MTA (postfix). Each request ties resources from postfix. If the IP is a known Spamhaus IP, snortsam will add this to iptables drop and postfix isn’t bothered with this ‚bad‘ traffic.

Looking at fail2ban, I was thinking this might be a good opportunity to lessen the load and B.S. interaction with the server. To get it installed:
 
apt-get install fail2ban
… and (if not already installed):
apt-get install whois
 
Copy the provided config file jail.conf to jail.local. Fail2ban will use this one, if it exists:
cp /etc/fail2ban/jail.conf  /etc/fail2ban/jail.local

 

Next we need to create our rules. I wanted to first handle the spamhaus/abuseat rejects.
Postfix rejects it, but the requests keep happening… so I want to block them for one hour:
 
Add the following section to /etc/fail2ban/jail.conf
[spam]
enabled  = true
filter   = spam
action   = iptables[name=SPAM, port=smtp, protocol=tcp]
logpath  = /var/log/mail.log
bantime  = 3600
ignoreip = 127.0.0.1 xxx.xxx.xxx.xxx
maxretry = 2

xxx.xxx.xxx.xxx = could be your NAT’d IP, or other IPs you want to make sure are never banned (eg: secondary MX, etc).
Also bantime is defaulted to 10 minutes, and I wanted to crank this up to 1 hour.
This is the config for creating a rule, next we need to define that rule. The rule will be titled spam.conf in filter.d/spam.conf

[Definition]
# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile. The
#          host must be matched by a group named "host". The tag "<HOST>" can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P<host>\S+)
# Values:  TEXT
#
failregex = : NOQUEUE: reject: RCPT from [-._\w]+\[<HOST>\]: (554 5\.7\.1 Service unavailable; Client host .* blocked using (sbl\.spamhaus\.org|cbl\.abuseat\.org)|550 5\.1\.1 .*(domain1|domain2|domain3)\.(ch|de|com)>: Recipient address rejected: User unknown in virtual alias table);
# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =

This rule has two regex rules combined there. The first rule will read the mail.log and looking for spamhaus.org or abuseat.org blacklist blocks. The second rule handles my unknown virtual user rejections with certain domains.

After we’ve configured fail2ban, and created our rule, we need to restart. One thing that I didn’t like is, that it didn’t tell you about any start up errors via the init script. I went ahead and edited the /etc/init.d/fail2ban and removed the „&> /dev/null“ so I could see the exact problems.
At this point you’ll be able to  tail -f /var/log/fail2ban.log  and watch bans and unbans happen. You’ll also want to test iptables to make sure fail2ban is being put into iptables:

iptables -L -n

You should see something like this:

Chain fail2ban-SPAM (1 references)

 

If you run into the problem that IPs are being completely dropped on all ports and all protocols, you’ll need to edit /etc/fail2ban/action.d/iptables.conf and change the following:

#actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
actionban = iptables -I fail2ban-<name> 1 -s <ip> -p <protocol> –dport <port> -j DROP

#actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
actionunban = iptables -D fail2ban-<name> -s <ip> -p <protocol> –dport <port> -j DROP

Block a single, nasty IP address:

iptables -A INPUT -s ipaddress -j DROP

or block a whole subnet (CIDR notation)

iptables -A INPUT -s XXX.YYY.ZZZ.0/24 -j DROP

Unban a specific ip address from a specific chain:

fail2ban-client set chain_name unbanip ipaddress

Remove a specific rule from a chain:
The first command will output a numbered list of rules, which were applied. Set num in the second command to the number in the num column of the list.

iptables -L chain_name -v -n  --line-numbers
iptables -D chain_name num