rails: RemoteIp middleware trusted proxies config does not affect Rack::Request::trusted_proxy?

I have clients that connect to my rails app from a private IP address, where the clients real IP is presented to rails via the X-Forwarded-For header (Thin cluster behind a pound load balancer). By default, rails assumes these private addresses are “trusted proxies”, which causes Request#remote_ip to return ‘127.0.0.1’.

This was somewhat addressed by pull request #2632 by making TRUSTED_PROXIES configurable in the RemoteIp Class.

However, Rails::Rack::Logger methods still call Rack::Request#ip which causes the IP address displayed in my logs to be 127.0.0.1.

Based on this change in rack: https://github.com/rack/rack/pull/192 It seems that ActionDispatch::Request should override Rack::Request#trusted_proxy? with the same “trusted proxies” that are configured for RemoteIp.

At the moment I have the following in an initializer to fix the problem for me, but it is obviously a really bad hack.

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

Does anyone have comments or suggestions otherwise? I can attempt a patch if my logic seems sound. Thanks.

About this issue

  • Original URL
  • State: closed
  • Created 12 years ago
  • Comments: 28 (9 by maintainers)

Commits related to this issue

Most upvoted comments

This bug is still present in Rails 5.0.0.1. Syntax changes a little, so, I had to add in

    #config/application.rb
    config.action_dispatch.trusted_proxies = %w(127.0.0.1 ::1).map { |proxy| IPAddr.new(proxy) }
    config.middleware.insert_before(Rails::Rack::Logger,
                                    ActionDispatch::RemoteIp,
                                    true,
                                    config.action_dispatch.trusted_proxies)
   #config/initializers/action_dispatch.rb
    module TrustedProxyMonkeyPatch
      def ip
        @ip ||= (get_header("action_dispatch.remote_ip") || super).to_s
      end
    end
    ActionDispatch::Request.send :include, TrustedProxyMonkeyPatch

Same issues here. I am using nginx + unicorn + rails 5.0.1 nginx configuration is same as https://www.digitalocean.com/community/tutorials/how-to-deploy-rails-apps-using-unicorn-and-nginx-on-centos-6-5

Atleast the request.remote_ip issue is resolved by following but logs are still incorrect in config/application.rb

# hopefully, this should not be breaking change if rails version changes!
config.action_dispatch.trusted_proxies = %w(127.0.0.1 ::1).map {
  |proxy| IPAddr.new(proxy) }

Steps to reproduce

(Guidelines for creating a bug report are available here)

Expected behavior

The logs should print correct remote ip

Actual behavior

started GET “/log_in” for 127.0.0.1 at <TIME>

System configuration

Rails version: 5.0.1 Ruby version: ruby 2.3.1p112

I experience the same issue. My private clients are within 192.168.0.0/16 network and the connections from them are proxied to rails through nginx, which sets X-Forwarded-For header with the correct ip address of the client. However because of hardcoded regexp of trusted_proxies in rack the client always ends up having an ip 127.0.0.1 (which is wrong). Unfortunately there is no way to configure this list in Rack/ActionDispatch without monkey patching the class as described by @edestecd.

The similar issue arises when request.remote_ip is called. (result is 127.0.0.1 instead of the expected 192.168.x.y) but at least the list of trusted proxies can be configured for ActionDispatch::RemoteIp middleware by adding the following code to config/environments/*.rb:

  config.action_dispatch.trusted_proxies = %r{
      ^127\.0\.0\.1$                | # localhost IPv4
      ^::1$                         | # localhost IPv6
      ^fc00:                        | # private IPv6 range fc00
      ^10\.                         | # private IPv4 range 10.x.x.x
      ^172\.(1[6-9]|2[0-9]|3[0-1])\.  # private IPv4 range 172.16.0.0 .. 172.31.255.255
    }x

(This if copy of ActionDispatch::RemoteIp::TRUSTED_PROXIES constant value without the last pattern matching 192.168.* network)

Given the fact the both Rack::Request#trusted_ip? (and its descendant ActionDispatch::Request#trusted_ip?) and ActionDispatch::RemoteIp#filter_proxies use essentially the same regexp it sounds natural to me to make ActionDispatch::Request#trusted_ip? use the value of config.action_dispatch.trusted_proxies