Limit_req seems to have no effect, but I would prefer it did

I’m attempting to rate limit requests, and I’m unable to make the
limit_req
directive have any effect. I’ve trimmed it down to a minimal test case.
Here’s my complete nginx.conf (with only the server_name changed to
protect
the innocent):


worker_processes 2;

events {
worker_connections 8192;
}

http {
#keepalive_timeout 0s;
#keepalive_requests 0;
#limit_conn_zone $binary_remote_addr zone=conn_res:10m;
#limit_conn conn_res 1;
limit_req_zone $binary_remote_addr zone=req_res:10m rate=1r/s;
limit_req zone=req_res;

server {
listen 80;
server_name example.com *.example.com;
location / {
return 410;
}
}
}

I’ve tried various combinations of burst=2, nodelay, 1r/s or 1r/m, with
and
without limit_conn, with and without keepalive, with and without
“location
/”, etc… and requests are never being limited, as shown by the
access.log
entries below:


while true; do
curl 55.55.55.55 -H’Host: test.example.com
done

12.34.56.78 - - [09/Oct/2012:08:47:03 +0000] “GET / HTTP/1.1” 410 158
“-”
“curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3”
12.34.56.78 - - [09/Oct/2012:08:47:03 +0000] “GET / HTTP/1.1” 410 158
“-”
“curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3”
12.34.56.78 - - [09/Oct/2012:08:47:03 +0000] “GET / HTTP/1.1” 410 158
“-”
“curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3”
12.34.56.78 - - [09/Oct/2012:08:47:04 +0000] “GET / HTTP/1.1” 410 158
“-”
“curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3”
etc…

The error.log file is empty. I’m running nginx 1.3.7, compiled from
source,
on an Amazon EC2 micro instance with the default image. (For kicks, I
also
tried 1.0.15, with no luck.) Here is /proc/version:

Linux version 3.2.21-1.32.6.amzn1.x86_64 (mockbuild@gobi-build-31004)
(gcc
version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) ) #1 SMP Sat Jun 23
02:32:15
UTC 2012

Am I missing something obvious here?

Posted at Nginx Forum:

On Tuesday 09 October 2012 13:20:00 zildjohn01 wrote:

I’m attempting to rate limit requests, and I’m unable to make the limit_req
directive have any effect. I’ve trimmed it down to a minimal test case.
Here’s my complete nginx.conf (with only the server_name changed to protect
the innocent):

[…]

limit_req_zone $binary_remote_addr zone=req_res:10m rate=1r/s;
limit_req zone=req_res;

server {
listen 80;
server_name example.com *.example.com;
location / {
return 410;
}
}
[…]

Am I missing something obvious here?

“return” is a directive from the rewrite module which works on the
rewrite
phase. “limit_req” works on the preaccess phase that comes later. So,
your
request doesn’t reach the limit_req module.

wbr, Valentin V. Bartenev

On Thursday 11 October 2012 05:17:19 zildjohn01 wrote:

That definitely explains the behavior I was seeing. But to me, any way to
bypass the rate limiter seems like a security hole.

Just “return 410;” is the much cheaper than the whole request
limitation thing.
And it’s a good reason to save the resources and don’t do limitation at
all in
this case.

The limit modules should be used to limit access to any resource
consumption
tasks, not trivial. Limiting for “return 410;” seems pointless to me.

Is there any way to change the phase/order of these two directives,

No, there is no way.

or to otherwise cause rewritten requests to be rate limited?

You can try some workaround like this:

location / {
try_files /410 @410;
}

location @410 {
return 410;
}

wbr, Valentin V. Bartenev

That definitely explains the behavior I was seeing. But to me, any way
to
bypass the rate limiter seems like a security hole. Is there any way to
change the phase/order of these two directives, or to otherwise cause
rewritten requests to be rate limited?

Posted at Nginx Forum: