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?
Once the rate limit of 10 requests per second is exceeded by a single client accessing /api/ , NGINX returns a “429 Too many requests” error to the client.
To limit connections, use the limint_conn directive to set the memory zone to be used and the maximum number of allowed connections as shown in the following configuration snippet. This directive is valid within the HTTP, server, and location contexts. Save the file and close it.
State information for about 16,000 IP addresses takes 1 ;megabyte, so our zone can store about 160,000 addresses. If storage is exhausted when NGINX needs to add a new entry, it removes the oldest entry.
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:
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With