Class: ActionDispatch::RemoteIp
| Relationships & Source Files | |
| Namespace Children | |
|
Classes:
| |
|
Exceptions:
| |
| Inherits: | Object |
| Defined in: | actionpack/lib/action_dispatch/middleware/remote_ip.rb |
Overview
This middleware calculates the IP address of the remote client that is making the request. It does this by checking various headers that could contain the address, and then picking the last-set address that is not on the list of trusted IPs. This follows the precedent set by e.g. the Tomcat server. A more detailed explanation of the algorithm is given at GetIp#calculate_ip.
Some Rack servers concatenate repeated headers, like HTTP RFC
2616 requires.
Some Rack servers simply drop preceding headers, and only report the value
that was given in the last
header.
If you are behind multiple proxy servers (like NGINX to HAProxy to
Unicorn) then you should test your ::Rack server to make sure your data is good.
IF YOU DON'T USE A PROXY, THIS MAKES YOU VULNERABLE TO IP SPOOFING. This
middleware assumes that there is at least one proxy sitting around and setting
headers with the client's remote IP address. If you don't use a proxy, because
you are hosted on e.g. Heroku without SSL, any client can claim to have any IP
address by setting the X-Forwarded-For header. If you care about that, then
you need to explicitly drop or ignore those headers sometime before this
middleware runs. Alternatively, remove this middleware to avoid inadvertently
relying on it.
Constant Summary
-
TRUSTED_PROXIES =
# File 'actionpack/lib/action_dispatch/middleware/remote_ip.rb', line 40
The default trusted IPs list simply includes IP addresses that are guaranteed by the IP specification to be private addresses. Those will not be the ultimate client IP in production, and so are discarded. See https://en.wikipedia.org/wiki/Private_network for details.
[ "127.0.0.0/8", # localhost IPv4 range, per RFC-3330 "::1", # localhost IPv6 "fc00::/7", # private IPv6 range fc00::/7 "10.0.0.0/8", # private IPv4 range 10.x.x.x "172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255 "192.168.0.0/16", # private IPv4 range 192.168.x.x "169.254.0.0/16", # link-local IPv4 range 169.254.x.x "fe80::/10", # link-local IPv6 range fe80::/10 ].map { |proxy| IPAddr.new(proxy) }
Class Method Summary
-
.new(app, ip_spoofing_check = true, custom_proxies = nil) ⇒ RemoteIp
constructor
Create a new
RemoteIpmiddleware instance.
Instance Attribute Summary
Instance Method Summary
-
#call(env)
Since the IP address may not be needed, we store the object here without calculating the IP to keep from slowing down the majority of requests.
Constructor Details
.new(app, ip_spoofing_check = true, custom_proxies = nil) ⇒ RemoteIp
Create a new RemoteIp middleware instance.
The ip_spoofing_check option is on by default. When on, an exception is
raised if it looks like the client is trying to lie about its own IP address.
It makes sense to turn off this check on sites aimed at non-IP clients (like
WAP devices), or behind proxies that set headers in an incorrect or confusing
way (like AWS ELB).
The custom_proxies argument can take an enumerable which will be used
instead of TRUSTED_PROXIES. Any proxy setup will put the value you want in
the middle (or at the beginning) of the X-Forwarded-For list, with your
proxy servers after it. If your proxies aren't removed, pass them in via the
custom_proxies parameter. That way, the middleware will ignore those IP
addresses, and return the one that you want.
# File 'actionpack/lib/action_dispatch/middleware/remote_ip.rb', line 67
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
Instance Attribute Details
#check_ip (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/remote_ip.rb', line 51
attr_reader :check_ip, :proxies
#proxies (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/remote_ip.rb', line 51
attr_reader :check_ip, :proxies
Instance Method Details
#call(env)
Since the IP address may not be needed, we store the object here without calculating the IP to keep from slowing down the majority of requests. For those requests that do need to know the IP, the GetIp#calculate_ip method will calculate the memoized client IP address.