Welcome! Log In Create A New Profile

Advanced

Re: Nginx Map how to check value if empty

B.R. via nginx
March 08, 2017 04:42AM
This kind of logic, as you found out, can be handled in nginx with the help
of the proper tools, namely the map module.
You are one step away: you can actually program what you require to be
feeding the realip module with the HTTP header name you ended up with.
Rather than having contiguous maps, head towards some cascading ones.

Have a look at the following example, specifically the precedence it
enforces and the fallback value (as needed) it provides.
map $http_x_foo $fooHeader {
default X-Foo;
"" "Nothing";
}

map $http_x_bar $myValue {
default X-Bar;
"" $fooHeader;
}

​This is scalable, configuration-wise.​
However, even if nginx is efficient at processing, it is always best to
keep in mind those maps will be evaluated for each request.
---
*B. R.*

On Wed, Mar 8, 2017 at 7:56 AM, c0nw0nk <nginx-forum@forum.nginx.org> wrote:

> Hey again,
>
> So I modified my config to this as to prevent client's IP spoofing.
>
>
> map $http_x_forwarded_for $client_ip_x_forwarded_for {
> "" $remote_addr; #if this header missing set remote_addr as real ip
> default $http_x_forwarded_for;
> }
> map $http_cf_connecting_ip $client_ip_from_cf {
> "" $client_ip_x_forwarded_for; #if this header missing set x-forwarded-for
> as real ip
> default $http_cf_connecting_ip;
> }
> map $remote_addr $client_ip_output {
> 192.168.0.12 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> 192.168.0.13 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> 192.168.0.14 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> 192.168.0.15 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
>
> default $remote_addr; #if none of ip matched then default to remote_addr
> }
>
>
>
>
> Don't know if i can do ranges in my map example above so I made a geo map
> too doing the exact same thing in case it may be better suited.
>
> geo $remote_addr $client_ip_output { #most likely should use geo for the
> range capability and other benefits
> 127.0.0.1 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> 192.168.1.0/24 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> 10.1.0.0/16 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> ::1 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
> 2001:0db8::/32 $client_ip_from_cf; #if ip match then it is a trusted ip
> (whitelist)
>
> default $remote_addr; #if none of ip matched then default to remote_addr
> }
>
>
> The usage of the final output is as easy as this. "$client_ip_output;"
> limit_req_zone $client_ip_output zone=one:10m rate=1r/s; #usage example for
> the resulting output after all fallback checks and ip whitelist checks etc.
>
>
> Based of what I showed here can anyone point out any problems they see with
> it etc from what I want to achieve I think it should work fine.
>
> IP whitelist basis, Fallback header's in case one is missing it goes to the
> next header for the realip, If the next header is missing it goes to the
> next until no more potential realip headers exist so we set their IP as
> their connection $remote_addr.
>
> Be nice if the realip module did this but lucky we don't need the realip
> module this shows and can do so with map's and geo maps.
>
>
> c0nw0nk Wrote:
> -------------------------------------------------------
> > Hey,
> >
> > I was just looking at the realip module but that module does not seem
> > to support fallback methods like I demonstrated I was in need of. (If
> > it does support multiple headers and fallback conditions can someone
> > provide a demonstration)
> >
> > If real_ip_header CF-Connecting-IP; is missing then fallback to
> > real_ip_header X-Forwarded-For; and if that header is missing use
> > $binary_remote_addr;
> >
> > I guess to prevent spoofing what if we merge the map's with a IP
> > header check map so we can keep our dynamic capabilities but check
> > that only the matching whitelisted IP's / IP ranges may send one of
> > those headers.
> > If a non whitelisted IP sends one of those headers we fall back to
> > $binary_remote_addr; making their spoofing pointless.
> >
> > That is the solution I can think of to prevent spoofing is to add to
> > the map's unless anyone has better or known way's that could be simple
> > or more easy.
> >
> > Francis Daly Wrote:
> > -------------------------------------------------------
> > > On Mon, Mar 06, 2017 at 02:12:40PM -0500, c0nw0nk wrote:
> > >
> > > Hi there,
> > >
> > > good that you've found some more answers.
> > >
> > > There's still some to be worked on, though, I suspect.
> > >
> > > > So to explain how to get the origin IP for each method someone
> > could
> > > be
> > > > using here is the list :
> > > >
> > > > Cloudflares proxied traffic :
> > > > sets the header $http_cf_connecting_ip so use this header to get
> > the
> > > > Client's real IP
> > >
> > > Stock nginx has the realip module which will allow you to use a
> > value
> > > from one specific http header, as if it were the connecting
> > address.
> > >
> > > And stock nginx knows that the client can set any header to any
> > value,
> > > so it can be configured to only believe the value if it was set by
> > a
> > > trusted source. (More or less).
> > >
> > > It looks like this $http_cf_connecting_ip contains a single IP
> > > address,
> > > which is the address of the thing that connected to Cloudflare --
> > > either
> > > the client, or a proxy that it uses. And it can be trusted, if the
> > > incoming request went through the Cloudflare reverse proxy. (And,
> > > presumably, it is spoofed if the incoming request did not go
> > through
> > > the Cloudflare reverse proxy.)
> > >
> > > > Traffic from cloudflare via the DNS only connections :
> > > > These would not have the $http_cf_connecting_ip header present.
> > > > But those connections hit a load balancing ip what sets the
> > header
> > > > $http_x_forwarded_for header so that is the way to get the
> > Clients
> > > real ip
> > > > via those connections.
> > >
> > > $http_x_forwarded_for is common enough; it can hold a list of IP
> > > addresses. The realip module knows how to deal with it.
> > >
> > > Whatever method you use to read it, you should be aware that the
> > > header is not necessarily exactly one IP address. And the client
> > can
> > > set the header to any initial value; the "load balancing ip"
> > (unless
> > > documented otherwise) probably creates-or-adds-to the header,
> > rather
> > > than creates-or-replaces.
> > >
> > > > And then some connections don't hit my load balancing IP and go
> > > directly to
> > > > a specific origin server these connections can use $remote_addr.
> > >
> > > They can. But those connections might also have
> > $http_x_forwarded_for.
> > > And
> > > $http_cf_connecting_ip. So you will need a reliable way of
> > > distinguishing
> > > between case#1 and case#2 and case#3, if you care about that.
> > >
> > > (Probably, the majority of "innocent" requests will not have
> > spoofed
> > > headers. If that is good enough for what you are trying to achieve,
> > > then you're ok.)
> > >
> > > > My Solution / conclusion :
> > > >
> > > > How to come up with a fix that allows me to obtain the real IP in
> > a
> > > dynamic
> > > > situation like this ?
> > >
> > > I would suggest one of:
> > >
> > > * go to extra measures to cause there to exist a new feature in
> > nginx,
> > > such that the realip module will look at more than one header to
> > > determine
> > > the address to use
> > >
> > > or
> > >
> > > * recognise that if Cloudflare put in a CF-Connecting-IP header,
> > they
> > > probably also put in a X-Forwarded-For header; ignore
> > CF-Connecting-IP
> > > and just use the realip module with X-Forwarded-For.
> > >
> > > http://nginx.org/r/real_ip_header and the rest of that page.
> > >
> > > > I have solved my issue with the following.
> > >
> > > This will work, with the above caveats.
> > >
> > > If you have time to experiment, you may find that the realip module
> > > does
> > > something similar in a less fragile way.
> > >
> > > Cheers,
> > >
> > > f
> > > --
> > > Francis Daly francis@daoine.org
> > > _______________________________________________
> > > nginx mailing list
> > > nginx@nginx.org
> > > http://mailman.nginx.org/mailman/listinfo/nginx
>
> Posted at Nginx Forum: https://forum.nginx.org/read.
> php?2,272744,272824#msg-272824
>
> _______________________________________________
> nginx mailing list
> nginx@nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx
>
_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Subject Author Posted

Nginx Map how to check value if empty

c0nw0nk March 03, 2017 10:47AM

Re: Nginx Map how to check value if empty

Francis Daly March 04, 2017 03:16AM

Re: Nginx Map how to check value if empty

c0nw0nk March 04, 2017 05:35PM

Re: Nginx Map how to check value if empty

c0nw0nk March 05, 2017 04:00PM

Re: Nginx Map how to check value if empty

B.R. via nginx March 05, 2017 04:40PM

Re: Nginx Map how to check value if empty

c0nw0nk March 05, 2017 04:50PM

Re: Nginx Map how to check value if empty

B.R. via nginx March 06, 2017 07:04AM

Re: Nginx Map how to check value if empty

c0nw0nk March 06, 2017 02:12PM

Re: Nginx Map how to check value if empty

Francis Daly March 07, 2017 04:26PM

Re: Nginx Map how to check value if empty

c0nw0nk March 07, 2017 06:44PM

Re: Nginx Map how to check value if empty

c0nw0nk March 08, 2017 01:56AM

Re: Nginx Map how to check value if empty

B.R. via nginx March 08, 2017 04:42AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 155
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready