NGINX: limit_req – limiting requests per IP
Tags: nginx
Published: 2019-08-12 08:03:27

---
title: NGINX: limit_req – limiting requests per IP
published: true
tags: NGINX
canonical_url: https://rtfm.co.ua/en/nginx-limit_req-limiting-requests-per-ip/
---

![](https://rtfm.co.ua/wp-content/uploads/2012/09/nginx_logo2.jpg)The next task is to set a limit per one IP to our backend’s API:

1. add requests limiter on the `/user/oauth/refresh_token` URI
2. set limit to 5 requests/minute from one IP
3. if the limit is reached – return _429 Too Many Requests_ response

Will use NGINX [`ngx_http_limit_req_module`](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html).

### `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;
...
```

[![](https://rtfm.co.ua/wp-content/uploads/2019/08/Screenshot_20190808_142819.png)](https://rtfm.co.ua/wp-content/uploads/2019/08/Screenshot_20190808_142819.png)

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 the [`ngx_stream_limit_conn_module`](http://nginx.org/en/docs/stream/ngx_stream_limit_conn_module.html#limit_conn_zone) 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 Headers](https://rtfm.co.ua/en/nginx-multi-branch-deployment-with-ansible-nginx-map-and-http-headers/)_
  - _`map $status $abnormal`: see the [NGINX: access log – log all except 200 responses](https://rtfm.co.ua/en/nginx-access-log-log-all-except-200-responses/)_
  - _`set_real_ip_from`: see the [NGINX: реальный IP в логах при работе за AWS Load Balancer](https://rtfm.co.ua/nginx-realnyj-ip-v-logax-pri-rabote-za-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;
    }
...
```

[![](https://rtfm.co.ua/wp-content/uploads/2019/08/Screenshot_20190808_142955.png)](https://rtfm.co.ua/wp-content/uploads/2019/08/Screenshot_20190808_142955.png)

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](https://scottlinux.com/2014/11/20/rate-limiting-with-nginx-behind-aws-elb/) 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](https://rtfm.co.ua/nginx-realnyj-ip-v-logax-pri-rabote-za-aws-load-balancer/) post, Rus)._

### Links

- [NGINX rate-limiting in a nutshell](https://www.freecodecamp.org/news/nginx-rate-limiting-in-a-nutshell-128fe9e0126c/)
- [Rate Limiting In Nginx](https://medium.com/@christopherphillips_88739/rate-limiting-in-nginx-5af7511ab3ce)
- [HTTP request processing phases in Nginx](http://www.nginxguts.com/2011/01/phases/)

### Similar posts

- <small>06/26/2019</small> [NGINX: multi-branch deployment with Ansible, NGINX map and HTTP Headers](https://rtfm.co.ua/en/nginx-multi-branch-deployment-with-ansible-nginx-map-and-http-headers/)
- <small>04/12/2017</small> [NGINX: динамический upstream](https://rtfm.co.ua/nginx-dinamicheskij-upstream/)
- <small>03/23/2017</small> [NGINX: бан User Agent](https://rtfm.co.ua/draft-nginx-ban-user-agent/)
- <small>03/17/2019</small> [NextCloud: installing server on Debian behind NGINX with PHP-FPM and client on Arch Linux](https://rtfm.co.ua/en/nextcloud-installing-server-on-debian-behind-nginx-with-php-fpm-and-client-on-arch-linux/)