Getting the hang of fail2ban

I kept finding strange things in my log files and I wanted an automated way of going through them and banning IPs that are trying weird stuff. The answer in this case was fail2ban and the example that I’m covering in this post is looking out for and banning IPs attempting to use my mail server as an open relay.

Getting the hang of fail2ban was pretty straightforward. Making new rules can be divided into the following :

  1. Identifying the problem in log files
  2. Making a regex to match the problem
  3. Creating a new jail
  4. Test if it works

Identifying the problem in log files

The log entries that were signaling open relay access attempts were like the one below :

Oct 18 01:20:09 hostname postfix/smtpd[29043]: NOQUEUE: reject: RCPT from unknown[]: 454 4.7.1 <[email protected]>: Relay access denied; from=<www@redacted.tld> to=<[email protected]> proto=ESMTP helo=<WIN-98I68H1667N>

To filter them in bash I used the following line :

cat /var/log/mail.log | grep -i “relay access denied”

To only get the IPs I would extend the line and have what’s below :

cat /var/log/mail.log | grep -i “relay access denied” | awk ‘{print $10}’ | awk ‘NR>1{print $1}’ RS=[ FS=]

Cool. Now we know how the problem looks like.

Making a regex to match the problem

Regex can be somewhat of a hassle at first, but if you get the hang of it can turn out to be really powerful. This case was relatively easy, as there were examples out there that could be modified. Fail2ban ships with some filters (/etc/fail2ban/filters.d/) and one of them is called “postfix.conf“, which contained regex patterns closely related to what I was looking for.

^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$

Looking at my log entry from above and the regex pattern, we can see that we only have to modify the STMP error codes included in the pattern.

^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 .*$

I’ve added the line in the “postfix.conf” file mentioned above. Now we have the pattern to match the problem.

Create a new jail

“Jails” are configuration files that fail2ban uses to link filters and actions. The default one is jail.local but I decided to have a separate file which would be automatically included there. The file should reside in /etc/fail2ban/jail.d/ and should end with “.conf”.

root@hostname:/etc/fail2ban# cat jail.d/postfix.conf
enabled = true
port = smtp
filter = postfix
logpath = /var/log/mail.log
maxretry = 2

Now, we just need to reload the configuration so that fail2ban starts applying it.

service fail2ban restart

The new jail can be checked in the status command by using the name given between the brackets (in this case “postfix”)

fail2ban-client status postfix

Test if it works

  1. With existent log files where you’ve detected the problem

Fail2ban has a nice utility that can check if your filters are working.

fail2ban-regex /var/log/mail.log.1 filter.d/postfix.conf

The output should be something like in the picture below.


2. Real-case scenario

Nothing beats a real-case scenario when testing your configuration. Let’s try a open relay scan using some online tools. While watching how the requests are being sent, check your logs in real time to see if things are working.

The mail log should indicate anything that’s hapening and that should be similar to the first log entry mentioned above.

tail -f /var/log/mail.log

At the same time, you should check your fail2ban log to see if IPs are getting banned (this would depend on your configuration, but in my case, an IP will be banned after 2 attempts – the “maxretry = 2” line from above)

tail -f /var/log/fail2ban.log

The most trickiest part would be in writing the actual regex – the good thing in this example is that we’ve already had something to start from. Besides that, is as straightforward as the 4 steps above.