Banning bots in nginx using fail2ban

Posted on Sep 24, 2020

Some days ago I started learning a bit more about fail2ban in order to ban bad HTTP petitions reaching my nginx server. Here is a brief of what I learnt and did.

fail2ban jails

Normally configured in /etc/fail2ban/jail.local file. In this file you configure fail2ban jails. Each jail will search for a type of bad behavior and ban IPs with that specific pattern. Here is an example of a little jail I made.


enabled = true
bantime  = 600
findtime  = 600
maxretry = 5
port = http, https
action = nginx-action
filter = nginx-block
logpath = /config/log/nginx/access.log

The parameters mean the following:

  • bantime: How many seconds will the ban last for detected offenders.
  • findtime: Window of time for offense check.
  • maxretry: How many offenses will be tolerated.
  • action: What to do with banned users. In this case, this action is defined in the nginx-action file.
  • filter: Definition of the offense. Just a regexp to find in the nginx logs. In this case, the filter is defined in the nginx-block file.
  • logpath: Log file to check for offenses.

In other words, fail2ban will search periods of findtime for matches in filter. If more than maxretry matches are found, the offender will be banned bantime, executing action action.

fail2ban filters

The /etc/fail2ban/filter.d/nginx-block.conf filter defines a pattern to search, and could look like this:

failregex = ^<HOST> - - \[.\] "." (400|401|403|404|405|404) .*$
ignoreregex =

This filter matches with some HTTP errors in the log file. <HOST> corresponds to the IP address in the log. If you want to ban users with other types of behaviors, you just need to change the filter according to the offense you want to match.

fail2ban actions

The /etc/fail2ban/action.d/nginx-action.conf action defines what to do with banned users. It can be whatever you want, from banning access to the server to sending a mail, executing a script… In this example, the action file looks like this:


actionstart = echo "" > /config/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
actionstop = echo "" > /config/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
actioncheck =
actionflush = echo "" > /config/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
actionban = echo -n "deny <ip>;" >> /config/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
actionunban = sed -i "s/deny <ip>;//g" /config/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload

The names are quite auto descriptive. When a user is banned, an nginx deny clause is appended to the fail2ban-ip.conf file. Of course, this file is then included in the nginx conf, accurately banning the IPs contained in this file. Other options for banning may be banaction = ufw or banaction = iptables-allports, which are firewall bans. Therefore, IPs banned with this methods will not even reach de nginx server.