How to log real client ip in rails log when behind proxy like nginx How to log real client ip in rails log when behind proxy like nginx nginx nginx

How to log real client ip in rails log when behind proxy like nginx


In my opinion, your current approach is the only sane one. The only step that is missing is overwriting the IP address in env.

The typical REMOTE_ADDR seldom holds the correct IP if you've any amount of layers of proxies and load balancers and what not -- you're not unique in this respect. Each potentially adds or changes remote IP-related headers. And you cannot assume that each of those fields necessarily correspond to a single IP address, at that. Some will push or unshift an IP to a list instead.

There is only one way to know for sure which field holds the correct value and how, and that is to dive in there and look. You've evidently done that already. Now, just overwrite env['REMOTE_ADDR'] with its correct value using your Rack middleware. There's little point in letting any piece of code you didn't write log or process the wrong IP address, as is happening now.

(This being Ruby, you could also monkey patch Rack::Request, of course...)

For colorful reading that illustrate the varying degrees of which exotic setups can mess up attempts at finding a client's real IP address, see for instance the unending discussions that occurred about this for WordPress:

It's PHP but the gist of the points raised apply equally well to Ruby. (Note that they're unresolved as I write this, too, and that they've been around for aeons.)


This seemed to do the trick for me. (set in nginx config)

   proxy_set_header CLIENT_IP $remote_addr;


I ran into the same issue, that a subset of our web clients access our rails app on (Rails 4.2.7) on our private network and we get the wrong IP reported. So, I thought I'd add what worked for us to resolve the problem.

I found Rails issue 5223 that provided a better workaround than double logging the IP like the question does. So, we monkey patch Rack to remove the private network from the list of trusted proxies like so:

module Rack  class Request    def trusted_proxy?(ip)      ip =~ /^127\.0\.0\.1$/    end  endend

That addresses the controller logging the wrong IP, the other half of the fix to ensure that request.remote_ip is handled correctly. To do so add the following to your config/environments/production.rb:

config.action_dispatch.trusted_proxies = [IPAddr.new('127.0.0.1')]