Mitigate DDoS attack with ngx_http_limit_req_module and fail2ban
The fail2ban do have comprehensive collection of scripts that scan log files and ban IPs that match malicious activities.
But we are going to look on how to use ngx_http_limit_req_module logs to ban IPs that shows sign of Distributed Denial of Service (DDoS) attack on your website.
It is assumed in this tutorial that Nginx server is installed in your server.
The following procedures are tested on running Centos 7 64-bit Linux distribution.
Enable ngx_http_limit_req_module by adding the following script in your Nginx configuration:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
…
server {
…
limit_req zone=one burst=5;
}
}
Restart Nginx server:
systemctl restart nginx.service
You will see entry something like this in Nginx error log if there’s abuse detected:
2015/08/27 02:18:05 [error] 21235#21235: *326 limiting requests, excess: 5.297 by zone “one”, client: 91.214.169.44, server: www.webfoobar.com, request: “GET /node/8 HTTP/1.1”, host: “www.webfoobar.com”, referrer: “https://www.webfoobar.com/archive/201502”
We will use this sample log entry for our fail2ban filter script.
Install fail2ban:
yum install -y fail2ban
Create fail2ban filter script based on the Nginx error log entry:
vi /etc/fail2ban/filter.d/nginx-ddos.conf
The content of this filter file:
[Definition]
failregex = limiting requests, excess:.* by zone.*client:
ignoreregex =
We will use the /etc/hosts.deny to block the IP of the DDoS attacker so we will need to create new fail2ban action script:
vi /etc/fail2ban/action.d/hostsdeny.conf
Add the following script as its content:
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = IP= &&
printf %%b “: $IP\n” >>
actionunban = IP= && sed -i.old /ALL:\ $IP/d
[Init]
file = /etc/hosts.deny
daemon_list = ALL
Enable the newly created fail2ban filter:
vi /etc/fail2ban/jail.local
Append the following script:
[nginx-ddos]
enabled = true
port = http,https
banaction = hostsdeny
findtime = 120
bantime = 7200
maxretry = 30
logpath = %(nginx_error_log)s
Start the fail2ban service:
systemctl start fail2ban
systemctl enable fail2ban.service
systemctl list-unit-files | grep fail2ban
To check the status of this fail2ban filter:
fail2ban-client status nginx-ddos
You will see something like this:
Status for the jail: nginx-ddos
|- Filter
| |- Currently failed: 18
| |- Total failed: 770
| `- File list: /var/log/nginx/nginx_error_log
`- Actions
|- Currently banned: 1
|- Total banned: 8
`- Banned IP list: 91.214.169.44
To test if the fail2ban nginx-ddos filter working:
fail2ban-regex /var/log/nginx/nginx_error_log /etc/fail2ban/filter.d/nginx-ddos.conf
You can use apache-bench to test the whole system:
ab -n 20 -c 10 http://www.example.com
Execute the following command to monitor the fail2ban log:
watch -n 1 tail -n 20 /var/log/fail2ban.log
And you will something like this while testing with apache-bench:
Recent Comments