Nginx reverse-proxy
Nginx is the solution when it comes to reverse proxy. It has a wide range of features for security and performances. Today, we will set up a basic protection in order to prevent login brute force attacks.
Rate limiting
Nginx is able to handle thousands of requests per second. In case of a brute force attack, the attacker would be able to try thousands of credentials per seconds! Rate limiting features will prevent such attacks by limiting the attempt per second. Limiting 1 attempt per second will considerably delay the possibility to find user credentials.
Limit amount of connection per IP
To mitigate DDOS attack, you should limit the amount of connection per IP. There are much better solutions to prevent DDOS but this can help.
Error code
Most attacks are coming from automated bots looking at http code returned by your server. By default, when rate is limited, Nginx will return a 503 (Server Temporarily Unavailable). By changing returned code to 444 (No response from server), most bots will move to the next target. It is also easier to track on server logs or monitoring systems.
Find Login URL
Prior to configuring Nginx, you will need to know the login url used by your application. Depending on software you use, your login access could be:
- /api/login for an API
- /wp-login for Wordpress
- /admin/login for a backend access
- /user/login for a frontend access
How to configure Nginx
Edit virtual server with your favorite editor:
#set login zone max 1 request per second per client
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
server_name example.com;
root /var/www/html/;
#limit connection per ip
limit_conn perip 10;
#protect /admin/login
location ~/admin/login {
limit_req zone=login; #use login limit_req_zone
limit_req_status 444; #return 444 when limiting
}
location / {
#other none rate limited requests
}
}
Testing
To test feature, you can run 3 requests in a row from command line:
curl http://example.com/admin/login -I; curl http://example.com/admin/login -I; curl http://example.com/admin/login -I;
First request should return an http code (200,401,403...). Following requests should return something like "curl: (52) Empty reply from server".
Server log:
your.client.ip - - [15/Jun/2020:23:40:11 +0000] "HEAD /admin/login HTTP/1.1" 200 0 "-" "curl/7.58.0"
your.client.ip - - [15/Jun/2020:23:40:11 +0000] "HEAD /admin/login HTTP/1.1" 444 0 "-" "curl/7.58.0"
your.client.ip - - [15/Jun/2020:23:40:11 +0000] "HEAD /admin/login HTTP/1.1" 444 0 "-" "curl/7.58.0"
Conclusion
By implementing basic features like rate limiting and max connection per IP, you will help in protecting your application and user data. This configuration doesn't take much time to configure and add an extra layer of security to your application.