NGINX: limit_req – limiting requests per IP
Arseny Zinchenko
Posted on August 12, 2019
The next task is to set a limit per one IP to our backend’s API:
- add requests limiter on the
/user/oauth/refresh_token
URI - set limit to 5 requests/minute from one IP
- if the limit is reached – return 429 Too Many Requests response
Will use NGINX ngx_http_limit_req_module
.
limit_req_zone
To make limiting works firs need to create a memory region to store IP addresses and requests from each.
Add it to the nginx.conf
, http {}
block:
...
limit_req_zone $binary_remote_addr zone=backend_oauth:10m rate=5r/m;
...
Here:
-
$binary_remote_addr
– a variable with a visitor’s IP -
zone=backend_oauth:10m
– memory zone named backend_oauth and 10 MB size ($binary_remote_addr
size can be found in thengx_stream_limit_conn_module
documentation) -
rate=5r/m
– 5 requests/minute limit
Also:
-
map $http_branch $app_branch
: see the NGINX: multi-branch deployment with Ansible, NGINX map and HTTP Headersmap $status $abnormal
: see the NGINX: access log – log all except 200 responsesset_real_ip_from
: see the NGINX: реальный IP в логах при работе за AWS Load Balancer (Rus)
limit_req
Next, in a virtual host’s config add a new location
where you want to apply limit and add limit_req
:
...
location ~ /v3/user/oauth/refresh_token/ {
limit_req zone=backend_oauth nodelay;
limit_req_status 429;
fastcgi_pass 127.0.0.1:9014;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param DOCUMENT_ROOT $root_path;
fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
fastcgi_intercept_errors on;
}
...
Check syntax, re-read configs:
root@bttrm-stage-app-2:/home/admin# nginx -t && systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Apache benchmark
Test it:
$ ab -n 100 -c 10 "https://stage.example.com/v3/user/oauth/refresh_token/"
Check logs:
root@bttrm-stage-app-2:/home/admin# tail -f /var/log/nginx/stage.example.com-access.log | grep 194.***.***.26
194.***.***.26 - - [08/Aug/2019:14:26:29 +0300] "GET /v3/user/oauth/refresh_token/ HTTP/1.1" 404 27 "-" "ApacheBench/2.3"
194.***.***.26 - - [08/Aug/2019:14:26:29 +0300] "GET /v3/user/oauth/refresh_token/ HTTP/1.1" 429 162 "-" "ApacheBench/2.3"
194.***.***.26 - - [08/Aug/2019:14:26:29 +0300] "GET /v3/user/oauth/refresh_token/ HTTP/1.1" 429 162 "-" "ApacheBench/2.3"
...
The 429 response was returned, all works.
NGINX, limit_req
and AWS ALB
Found a possible issue when using AWS ALB (but this was posted at 2014): with the $binary_remote_addr
limits may not works, if so – try to use $http_x_forwarded_for
instead.
Although in my current case everything was fine, maybe because of the я set_real_ip_from
(see the NGINX: реальный IP в логах при работе за AWS Load Balancer post, Rus).
Links
Similar posts
Posted on August 12, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024