8

This is my nginx configuration:

{
    # on top of conf file
    limit_req_zone $binary_remote_addr zone=main:10m rate=1r/s;  
    ...

    location /login {
            limit_req zone=main burst=3 nodelay;
            ModSecurityEnabled on;
            ModSecurityConfig /usr/local/nginx/conf/modsecurity.conf;
            proxy_pass http://localhost:4000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}

When hitting the api url (http://localhost:4000/login) multiple times using following code -

for i in {0..2000}; do (curl -Is http://localhost:4000/login | head -n1 &) 2>/dev/null; done

I am getting always getting 200 response code instead of getting 503 for some requests which should be rejected. Why is this happening?

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
Anshul Bisht
  • 1,644
  • 20
  • 21

2 Answers2

6

For me limit_req was not working too. The issue was in wrong ordering - limit_req should come before proxy_pass

Works:

limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

server {
  listen      443;
  server_name example.com;

  limit_req zone=req_limit_per_ip burst=10 nodelay;

  location / {
    proxy_pass         http://be_server;
  }
}

Works

limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

server {
  listen      443;
  server_name example.com;

  location / {
    limit_req zone=req_limit_per_ip burst=10 nodelay;

    proxy_pass         http://be_server;
  }
}

Doesn't work

limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

server {
  listen      443;
  server_name example.com;

  location / {
    proxy_pass         http://be_server;

    limit_req zone=req_limit_per_ip burst=10 nodelay;
  }
}
srghma
  • 4,770
  • 2
  • 38
  • 54
5

This is my config. Now it is correctly displaying the 200 & 503 requests after passign tthe threshold.

limit_req_zone $http_x_forwarded_for zone=req_limit_per_ip:100m rate=10r/m;
limit_conn_zone $http_x_forwarded_for zone=conn_limit_per_ip:100m;


server {

listen 80;

server_name *.xxxxxx.com;
add_header 'Access-Control-Allow-Headers' "X-Forwarded-For; X-Forwarded-Proto; X-Forwarded-Port; Host; X-Amzn-Trace-Id; Connection";
#add_header 'Access-Control-Allow-Headers' "X-Requested-With";
add_header 'Access-Control-Allow-Methods' "GET, POST, OPTIONS";
#add_header 'Access-Control-Allow-Origin' "$http_origin";

server_tokens off;
client_body_timeout 60s;
client_header_timeout 60s;
add_header 'X-Frame-Options' "SAMEORIGIN";
add_header 'Strict-Transport-Security' "max-age=31536000; includeSubDomains" ;

location /api/ {
    ModSecurityEnabled off;
    ModSecurityConfig /usr/local/nginx/conf/modsecurity.conf;
    limit_req zone=req_limit_per_ip burst=10 nodelay;
    proxy_pass http://xx.xxx.xxx.xxx:7000/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
    proxy_connect_timeout       60s;
    proxy_send_timeout          60s;
    proxy_read_timeout          60s;
    send_timeout                60s;

}
}

To check the effect, I created a .js file and requested the above url 20 times inside a loop. You can check the results below -

Output: enter image description here

Anshul Bisht
  • 1,644
  • 20
  • 21
  • Hi Anshul, just question Am I able to limit all locations? for example I would like to limit request during dir bruteforcing attack. Is that possible? Thank you – TomRavn Jun 05 '19 at 17:14
  • But now you dont have a limit_req setting ? how does this work ? – Chris Milburn Jun 19 '19 at 10:31
  • @ChrisMilburn you can limit_req setting under locations specified – Anshul Bisht Jun 24 '19 at 10:56
  • @Nikix I have not tried this for all locations but may be you can. Just try and confirm if it is working. – Anshul Bisht Jun 24 '19 at 10:59
  • 1
    Picked up from nginx's doc - The limit_req_zone directive sets the parameters for rate limiting and the shared memory zone, but it does not actually limit the request rate. For that you need to apply the limit to a specific location or server block by including a limit_req directive there. In the example, we are rate limiting requests to /login/. See https://www.nginx.com/blog/rate-limiting-nginx/ – Anshul Bisht Jun 24 '19 at 11:00
  • @AnshulBisht That is my point, you dont set limit_req in your config so how does it work for you ? – Chris Milburn Jul 01 '19 at 08:11
  • 1
    @ChrisMilburn I am actually using it...The answer posted above has no mention of limit_req (don't know why) but if you look at the real question posted by me, there you can see "limit_req" usage. I have edited my answer now. – Anshul Bisht Jul 01 '19 at 13:08
  • I think that this answer is not well explained. What configurations have you made, in order to make the rate limit configuration work? You just pasted a newer version of your configuration, without further explanation of what was changed. – ivanleoncz Dec 16 '20 at 01:29
  • What is `limit_conn_zone ` for, if it's not used anywhere? – nssmart Jul 07 '23 at 14:19