I use a few open source packages to help automate some defensive responses against hackers to my server. One is fail2ban. fail2ban can be configured to monitor pretty much any system daemon that produces a log file.

I also use CloudFlare, which is a CDN and DNS service that amongst its many features is automatic protection against malicious attacks (DDoS, SQL injections, comment spamming, etc). In addition, if there are IPs that slip through their detection, you can add them manually to your CloudFlare blacklist. Automatically detecting these additional IPs, and adding them to CloudFlare, is where fail2ban comes in.

So on to my scenario: I noticed some very specific, recurring HTTP requests on my server that served no purpose other than to probe for a vulnerability or to attack my server, a perfect scenario for creating a fail2ban “jail.” A fail2ban jail is a combination of a fail2ban filter and action. Typically you have a jail configured to block an IP at the iptables level, but I wanted it to be blocked at the CloudFlare level as well.

Setting up a fail2ban jail is pretty straightforward. The jail contains all the information that fail2ban needs to detect and act upon a matched condition. In a typical fail2ban install, you’ll find the jail.conf file, where all the jails are defined, at /etc/fail2ban/jail.conf

Creating a new fail2ban jail

Creating a new jail is as simple as adding something like so to jail.conf:

[some-jail-name]
enabled  = true
filter   = my-filter-name
action   = iptables-allports[name=some-jail-name, protocol=tcp]
           cloudflare-blacklist
           sendmail-whois[name=some-jail-name, dest=me@example.com]
logpath  = /var/log/some/log
maxretry = 0
bantime  = 604800

This creates a fail2ban filter called “some-jail-name”, scanning the log “/var/log/some/log” defined by “logpath,” applying the filter “my-filter-name” defined by “filter” on said log, and acting upon a match with the action(s) defined by “action” by doing the following: 1) block the IP in iptables, 2) block the IP at CloudFlare, and 3) send me a notification email. (Consult the fail2ban manual on jail options to see what they all mean)

Creating the fail2ban filter

The filter “my-filter-name” would then be defined at /etc/fail2ban/filter.d/my-filter-name.conf. Make sure to modify the failregex regex string to match what you are looking for in the log file. Be sure to consult the section on testing your filters in the fail2ban manual to confirm your filter works correctly.

[Definition]

# Option:  failregex
# Notes.:  regex to match the password failure 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 = ^<HOST> -.*POST /tmp.*$ 

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =

Creating the fail2ban action

And finally, the action “cloudflare-blacklist” is defined at /etc/fail2ban/action.d/cloudflare-blacklist.conf. It will call CloudFlare’s client API to add/remove an IP from your blacklist. 

In order to configure your action properly:

  1. Go to your CloudFlare account settings page to get your API key (it should be near the bottom of the page)
  2. In the actionban and actionunban sections, replace CLOUDFLARE_API_TOKEN with your API key
  3. In the actionban and actionunban sections,replace CLOUDFLARE_LOGIN with your CloudFlare login email
# Fail2Ban configuration file
#
# Author: Norman Yee
#
# $Revision$
#

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart =

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop =

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck =

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    &lt;ip&gt;  IP address
#          &lt;failures&gt;  number of failures
#          &lt;time&gt;  unix timestamp of the ban time
# Values:  CMD
#
actionban = curl -s "https://www.cloudflare.com/api.html?a=ban&key=<ip>&u=CLOUDFLARE_LOGIN&tkn=CLOUDFLARE_API_TOKEN"

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    &lt;ip&gt;  IP address
#          &lt;failures&gt;  number of failures
#          &lt;time&gt;  unix timestamp of the ban time
# Values:  CMD
#
actionban = curl -s "https://www.cloudflare.com/api.html?a=nul&key=<ip>&u=CLOUDFLARE_LOGIN&tkn=CLOUDFLARE_API_TOKEN"

Once you have the jail, filter, and action set up and configured in fail2ban, you should be all set, with an additional layer of security courtesy of CloudFlare!