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
.
Contents
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 IPzone=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:
[simterm]
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
[/simterm]
Apache benchmark
Test it:
[simterm]
$ ab -n 100 -c 10 "https://stage.example.com/v3/user/oauth/refresh_token/"
[/simterm]
Check logs:
[simterm]
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" 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" ...
[/simterm]
429 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).