class ActionDispatch::RemoteIp

relying on it.
middleware runs. Alternatively, remove this middleware to avoid inadvertently
you need to explicitly drop or ignore those headers sometime before this
address by setting the ‘X-Forwarded-For` header. If you care about that, then
you are hosted on e.g. Heroku without SSL, any client can claim to have any IP
headers with the client’s remote IP address. If you don’t use a proxy, because
middleware assumes that there is at least one proxy sitting around and setting
IF YOU DON’T USE A PROXY, THIS MAKES YOU VULNERABLE TO IP SPOOFING. This
Unicorn) then you should test your Rack server to make sure your data is good.
If you are behind multiple proxy servers (like NGINX to HAProxy to
header](andre.arko.net/2011/12/26/repeated-headers-and-ruby-web-servers).
that was [given in the last
Some Rack servers simply drop preceding headers, and only report the value
2616](www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2) requires.
Some Rack servers concatenate repeated headers, like [HTTP RFC
detailed explanation of the algorithm is given at GetIp#calculate_ip.
server](issues.apache.org/bugzilla/show_bug.cgi?id=50453). A more
trusted IPs. This follows the precedent set by e.g. [the Tomcat
address, and then picking the last-set address that is not on the list of
the request. It does this by checking various headers that could contain the
This middleware calculates the IP address of the remote client that is making
# Action Dispatch RemoteIp

def call(env)

calculate the memoized client IP address.
those requests that do need to know the IP, the GetIp#calculate_ip method will
calculating the IP to keep from slowing down the majority of requests. For
Since the IP address may not be needed, we store the object here without
def call(env)
  req = ActionDispatch::Request.new env
  req.remote_ip = GetIp.new(req, check_ip, proxies)
  @app.call(req.env)
end

def initialize(app, ip_spoofing_check = true, custom_proxies = nil)

addresses, and return the one that you want.
`custom_proxies` parameter. That way, the middleware will ignore those IP
proxy servers after it. If your proxies aren't removed, pass them in via the
the middle (or at the beginning) of the `X-Forwarded-For` list, with your
instead of `TRUSTED_PROXIES`. Any proxy setup will put the value you want in
The `custom_proxies` argument can take an enumerable which will be used

way (like AWS ELB).
WAP devices), or behind proxies that set headers in an incorrect or confusing
It makes sense to turn off this check on sites aimed at non-IP clients (like
raised if it looks like the client is trying to lie about its own IP address.
The `ip_spoofing_check` option is on by default. When on, an exception is

Create a new `RemoteIp` middleware instance.
def initialize(app, ip_spoofing_check = true, custom_proxies = nil)
  @app = app
  @check_ip = ip_spoofing_check
  @proxies = if custom_proxies.blank?
    TRUSTED_PROXIES
  elsif custom_proxies.respond_to?(:any?)
    custom_proxies
  else
    raise(ArgumentError, <<~EOM)
      Setting config.action_dispatch.trusted_proxies to a single value isn't
      supported. Please set this to an enumerable instead. For
      example, instead of:
      config.action_dispatch.trusted_proxies = IPAddr.new("10.0.0.0/8")
      Wrap the value in an Array:
      config.action_dispatch.trusted_proxies = [IPAddr.new("10.0.0.0/8")]
      Note that passing an enumerable will *replace* the default set of trusted proxies.
    EOM
  end
end