4.3.5. Simple protection against bots (admin panel brute force) using nginx

You can protect your site from brute-force hacking (by guessing a password to the site's admin panel) and reduce the load created by hacking bots using nginx installed by the frontend on the server by modifying its configuration file (most often it is located in /etc/nginx/nginx.conf) in this way — right after the line http { add:

# antibot limit_req_zone $binary_remote_addr zone=antibot:16m rate=6r/m;
limit_req_log_level warn;
limit_req_status 403;

Next, find a block describing a specific protected site. It starts with server { and contains the directive server_name with the site address. Something like:

server {
server_name example.com www.example.com; listen xxx.xxx.xxx.xxx; # and then a series of locations describing the rules for processing requests to the server

V server add location with content like this:

location = /wp-login.php {
limit_req   zone=antibot burst=2 nodelay;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;


  • /wp-login.php — path to the protected page. For OpenCart, you need to replace it with /admin, for Joomla! — on /administrator.
  • — replace with the IP address: the port of the web server on which the site is hosted (you can spy it in the adjacent directives location).

Save the changes and check the correctness of the configuration file by running the command in the server console:

nginx -t

If the result of the check "syntax is ok"then restart nginx:

service nginx restart

This configuration file defines a shared memory zone called antibot, 16 MB in size and a request processing speed of 6 requests / minute or 1 access to /wp-login.php in 10 seconds (you can still specify this parameter in requests / second — r / s). If the number of incoming requests is greater than the rate value, their processing is postponed until their number exceeds the value specified in limit_req...burst (in our case — 2), after which all subsequent requests will receive a 403 error in response (you can set any other error code in the line limit_req_status, for example 423, as more accurate for determining the situation), given by nginx, which is much more economical in terms of resources consumed by the server than catching the same situation and blocking at the Apache level.

More information on configuring the module ngx_http_limit_req_module can be found in official nginx documentation.

Using the ab utility (apache benchmark), you can create an HTTP flood to a specific page, for example /wp-login.php, and look at the nginx Error log:

ab -n 100 -c 1 http://example.com/wp-login.php