Uncategorized

Help your mail server with fail2ban

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 techniques 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 my mail MTA (postfix + mysql). Each requests ties resources from postfix, and I burn mysql connections performing mailbox lookups. If the IP is a know spamhaus IP, snortsam will add this to iptables drop and postfix/mysql isn’t bothered with this ‘bad’ traffic.


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 techniques 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 my mail MTA (postfix + mysql). Each requests ties resources from postfix, and I burn mysql connections performing mailbox lookups. If the IP is a know spamhaus IP, snortsam will add this to iptables drop and postfix/mysql isn’t bothered with this ‘bad’ traffic.

Another great piece is using policyd-weight, which I’ve discussed in the past. Policyd-weight is a daemon that sits in line of postfix. Postfix will send header information before the data layer is transferred. This saves resources as well as bandwidth. Policyd-weight then performs various checks and assigns a score. If the score is high enough, it’ll reject the mail before data layer is sent.

During a recent spam barrage, I was noticing that policyd-weight was being bypassed because of null envelop sender (still working on this issue), and it was getting passed to postfix. Postfix would then do mailbox lookups and reject when a mailbox was not found. Unfortunately this was adding up to be in the thousands for a single domain. On another domain, I was seeing heavy ‘Relay access denied’ from random IP/hosts. So here I am with two domains that are getting hit hard with two different techniques. Along with these two types of requests, I was seeing lots of spamhaus/njabl blocks (from postfix).

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 (I’m a Gentoo guy)


emerge -v fail2ban

Next we need to make some configurations. First off it puts the socket into /tmp. I usually hate that, so I wanted to change this to /var/run


vi /etc/fail2ban/fail2ban.conf

and change the following:


socket = /var/run/fail2ban.sock

Next we need to create our rules. I wanted to first handle the spamhaus/njabl rejects. Postfix rejects it, but the requests keep happening… so I want to block them for one hour.


vi /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 not 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 = : warning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed$

failregex = : NOQUEUE: reject: RCPT from [-._\w]+\[<HOST>\]: 554 5.7.1 Service unavailable; Client host .* blocked using (sbl-xbl.spamhaus.org|combined.njabl.org);
: NOQUEUE: reject: RCPT from [-._\w]+\[<HOST>\]: 554 5.7.1 .*(domain1|domain2|domain3|domain4).com>: Relay access denied;
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

This rule has two regex rules listed there. The first rule will read the mail.log and looking for spamhaus or njabl blacklist blocks. The second rule handles my relay access denied 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 the /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)

I ran into a problem that IP were being completely dropped on all ports and protocols. This was weird since the jail.conf, you get to specify these values:
action = iptables[name=SPAM, port=smtp, protocol=tcp]

I found the problem, you’ll need to edit /etc/fail2ban/action.d/iptables.conf and change the following:


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

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

You can have emails sent on bans, but this was causing additional load on the server, and since I’d be receiving hundreds/thousands of emails, it didn’t matter anyway. Depending on your situation, you might want to add mail handling, and the example configuration shows how to do that. Also, you’ll want to be careful on what you want to block. It will be extremely to be too aggressive and DoS your own box to the public. Make sure your regex is good, and specific vs broad. Test, verify and test some more. Once, I added fail2ban to the server, I watched my load to take a dip and I could almost hear a sigh of relief coming from the box.

Along with mail, you could limit issues with your FTP server, SASL logins, web attacks and so on. It’s important to stop noisy attacks and be proactive with your server defense. Definitely fail2ban should be one of the tools on the box.