limit_req is not working with dynamically extracted user address

Maxim Dounin mdounin at mdounin.ru
Fri Mar 18 14:21:32 UTC 2016


Hello!

On Fri, Mar 18, 2016 at 09:45:58AM -0400, malish8632 wrote:

> Hi, if our HTTP block looks like below where we find IP from X-Forwarded-For
> using perl module it looks like zone and limit_req are not using correct
> variable $user_real_ip or it is reset right after logging.
> 
> The nginx_access_log shows the first logged field correctly as $user_real_ip
> - which is first element of comma separated IP addresses in X-Forwarded-For
> header from different hopes. User request comes thorough several different
> CDN and DDOS services.
> 
> But when limit_req kicks in it would take for some reason last element in
> same header X-Forwarded-For which of course not our intention.
> 
> Can you help understand why and what we are doing wrong?

How did you found that limit_req uses a wrong element?

Note: 

> 2016/03/17 17:44:15 [error] 19382#0: *8 limiting requests, excess: 5.613 by
> zone "one", client: 333.101.98.188, server: www.my.com, request: "GET
> /our/api/here HTTP/1.1", host: "www.my.com"

The "client: 333.101.98.188" is the client address as automatically 
logged by nginx for all error messages (also known as $remote_addr).  
It's not related to the limit string used by limit_req.

[...]

>     perl_set $user_real_ip '
> 
>         sub {
>             my $r = shift;
>             my $str = $r->header_in("X-Forwarded-For");
>             my @fields = split /,/, $str;
>             my $real_ip = $fields[0];
>             return $real_ip;
>         }
> 
>     ';

Note well: this can be easily tricked by clients using a fake 
address in initial X-Forwarded-For header.  You may want to use 
the realip module instead, it allows to trust only known proxies, 
see here:

http://nginx.org/en/docs/http/ngx_http_realip_module.html

-- 
Maxim Dounin
http://nginx.org/



More information about the nginx mailing list