Home > Blog > How to Use Fail2ban and Nginx to Implement Temporary IP Bans and Rate Limiting

How to Use Fail2ban and Nginx to Implement Temporary IP Bans and Rate Limiting

Background and Introduction

Denial-of-service (DoS) attacks are a common threat to web servers and other online services. These attacks attempt to overwhelm a server with traffic, making it unavailable to legitimate users. Nginx is a popular web server that is known for its performance and scalability. However, it is still vulnerable to DoS attacks.

One way to mitigate DoS attacks is to use rate limiting. Rate limiting allows you to limit the number of requests that a single IP address can make to your server in a given time period. This can help to prevent malicious actors from flooding your server with traffic.

Fail2ban is a software application that monitors log files for malicious activity. When Fail2ban detects suspicious activity, it can take a variety of actions, such as blocking the offending IP address.

By combining Nginx rate limiting with Fail2ban, you can create a powerful defense against DoS attacks. Nginx can be used to limit the rate of requests from a single IP address, and Fail2ban can be used to block IP addresses that exceed the rate limit.

This combination of technologies can be used to implement temporary IP bans. When a client IP address exceeds the rate limit, Fail2ban can block the IP address for a specified period of time. This can help to prevent the attacker from continuing their attack.

Fail2ban Installation

To install Fail2ban in Ubuntu or Debian, run the following command:

Create a Nginx filter file, using any text editor that you like:

nano /etc/fail2ban/filter.d/nginx-req-limit.conf

Add these lines:

# Fail2Ban configuration file
#
# supports: ngx_http_limit_req_module module

[Definition]

failregex = limiting requests, excess:.* by zone.*client: <HOST>

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

Create a new jail config:

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
nano /etc/fail2ban/jail.local

Add these config into jail.local file:

...
[nginx-req-limit]

enabled = true
filter = nginx-req-limit
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = /var/log/nginx/*error.log
findtime = 600
bantime = 60
maxretry = 10

...

You can configure the bantime in seconds. For example, I set it to 60 seconds for any public IP that does DoS or requests spam. This means that the public IP will be listed in the firewall blocklist for 60 seconds and not be able to access any web application in HTTP and HTTPS protocol for 60 seconds.

After configuring the jail.local file, restart the Fail2ban service:

You can check the service status by running this command:

fail2ban-client status nginx-req-limit

It will look something like this:

If you see this output, it means that the Fail2Ban has been configured successfully. It’s not done yet, you need to configure the Nginx to be the “trigger” for the Fail2Ban. Now let’s go into Nginx configuration.

Nginx setup

In this implementation, I configure the IP ban and rate limiting in the global nginx.conf file, in which applies to all of my web applications behind reverse proxies and virtual hosts, directly in http{} block, and it looks like this:

http{
   ...
   limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
   limit_req   zone=one burst=10;
   ...
}

Don’t forget to test the Nginx config with sudo nginx -t, then reload or restart the Nginx to apply the configuration. At this point, the rate limiter and the IP temporary ban are already running.

Testing

To test the Fail2ban, you can use tools like Siege, which is a load balancer tester that can also be used to stress test the rate limiter. In before, using the fail2ban-client status nginx-req-limit command, the output looked like this:

This means that there’s no public IP that spam requests your web application. However, using Siege, Fail2Ban, using Nginx’s rate limiter module, successfully blocks the DoS attack, by putting it in a “jail”, which is an automated firewall that blocks HTTP requests from that IP temporarily for 1 minute.

By implementing this, you can save your CPU bandwidth from a DoS attack, since a DoS attack does not just overwhelm your bandwidth, but also your CPU utilization, especially for a web application that relies heavily on SQL queries, or even disk I/O for each GET request. This can also block any login brute force attempt, especially by adding an HTTP login attempt limiter in Fail2ban.

This method can effectively mitigate DoS attempts, but one thing that you should know is that this method is possibly less effective, but still helpful to mitigate DDoS attacks since attackers can use multiple public IPs, but attackers also require a lot of effort to do DDoS, such by infecting multiple computers by botnet in which attackers might getting more “loss” compared to victim target.

If you are concerned about DDoS, and being targeted, you may look for a Web Application Firewall (WAF), such as CloudFlare’s proxy, Amazon CloudFront, or any cloud provider that offers load balancing and CDN services.

Leave a Reply

Your email address will not be published. Required fields are marked *