Nginx Map how to check value if empty

Francis Daly francis at
Tue Mar 7 21:23:59 UTC 2017

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


* 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. 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.


Francis Daly        francis at

More information about the nginx mailing list