Rate limiting requests per IP address in Nginx

Just wanted to post this here, since I've had to do this from time to time, and always had to read through the docs and try to build my own little example of it...

If you're trying to protect an Nginx server from a ton of traffic (especially from a limited number of IP addresses hitting it with possibly DoS or DDoS-type traffic), and don't have any other protection layer in front, you can use limit_req to rate limit requests at whatever rate you choose (over a given time period) for any location on the server.

# Add this to your virtual host config file.
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

# Later, in a `server` block:
server {
    location ~ \.php$ {
        limit_req zone=mylimit;
        ...
    } 
    ...
}

I have had to do this sometimes when I noticed a few bad IPs attacking my servers. You can adjust the rate and zone settings to your liking (the above settings limit requests to any PHP script to 10 per second over a 10 minute period).

You may also be interested in selectively blocking POST requests for certain IP addresses/ranges.

Comments

I recommend limiting the request on the network level if it is per ip with iptables and ipset, but you will lose the control to limit per-path.

Yeah, there are tradeoffs at each layer—the further from the application, the more blunt the restrictions have to be, unfortunately. But it's definitely better to prevent the malicious traffic at the edge furthest from your application servers, if possible.

This "over a 10 minute period" might be wrong. "10m" in the zone is about the size of the zone, not time frame or eviction policy of the old entries.

Here is a reference. Other sources confirming this can also be found by a little search.
https://www.nginx.com/blog/rate-limiting-nginx/

Hope this helps and thanks for the nice article!