aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Arko <andre@arko.net>2011-11-12 00:45:31 -1000
committerAndre Arko <andre@arko.net>2011-11-12 00:45:31 -1000
commit317f4e22365e2d9b8200aefbda943798e8f85a82 (patch)
treeb12523dfd63d67d3c183a4005fed555cd55b5823
parent9432163c60fc4387d1dfb11ca7c92a08ce72f1c2 (diff)
downloadrails-317f4e22365e2d9b8200aefbda943798e8f85a82.tar.gz
rails-317f4e22365e2d9b8200aefbda943798e8f85a82.tar.bz2
rails-317f4e22365e2d9b8200aefbda943798e8f85a82.zip
defer calculating the remote IP until requested
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb60
1 files changed, 36 insertions, 24 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index 79f9ddcd04..3b813b03bb 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -13,6 +13,8 @@ module ActionDispatch
)\.
}x
+ attr_reader :check_ip_spoofing, :trusted_proxies
+
def initialize(app, check_ip_spoofing = true, custom_proxies = nil)
@app = app
@check_ip_spoofing = check_ip_spoofing
@@ -24,35 +26,45 @@ module ActionDispatch
end
end
- # Determines originating IP address. REMOTE_ADDR is the standard
- # but will be wrong if the user is behind a proxy. Proxies will set
- # HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR, so we prioritize those.
- # HTTP_X_FORWARDED_FOR may be a comma-delimited list in the case of
- # multiple chained proxies. The last address which is not a known proxy
- # will be the originating IP.
def call(env)
- client_ip = env['HTTP_CLIENT_IP']
- forwarded_ips = ips_from(env, 'HTTP_X_FORWARDED_FOR')
- remote_addrs = ips_from(env, 'REMOTE_ADDR')
-
- if client_ip && @check_ip_spoofing && !forwarded_ips.include?(client_ip)
- # We don't know which came from the proxy, and which from the user
- raise IpSpoofAttackError, "IP spoofing attack?!" \
- "HTTP_CLIENT_IP=#{env['HTTP_CLIENT_IP'].inspect}" \
- "HTTP_X_FORWARDED_FOR=#{env['HTTP_X_FORWARDED_FOR'].inspect}"
- end
-
- remote_ip = client_ip || forwarded_ips.last || remote_addrs.last
- env["action_dispatch.remote_ip"] = remote_ip
+ env["action_dispatch.remote_ip"] = GetIp.new(env, self)
@app.call(env)
end
- protected
+ class GetIp
+ def initialize(env, middleware)
+ @env, @middleware = env, middleware
+ end
+
+ # Determines originating IP address. REMOTE_ADDR is the standard
+ # but will be wrong if the user is behind a proxy. Proxies will set
+ # HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR, so we prioritize those.
+ # HTTP_X_FORWARDED_FOR may be a comma-delimited list in the case of
+ # multiple chained proxies. The last address which is not a known proxy
+ # will be the originating IP.
+ def to_s
+ client_ip = @env['HTTP_CLIENT_IP']
+ forwarded_ips = ips_from('HTTP_X_FORWARDED_FOR')
+ remote_addrs = ips_from('REMOTE_ADDR')
- def ips_from(env, header)
- ips = env[header] ? env[header].strip.split(/[,\s]+/) : []
- ips.reject{|ip| ip =~ @trusted_proxies }
+ check_ip = client_ip && @middleware.check_ip_spoofing
+ if check_ip && !forwarded_ips.include?(client_ip)
+ # We don't know which came from the proxy, and which from the user
+ raise IpSpoofAttackError, "IP spoofing attack?!" \
+ "HTTP_CLIENT_IP=#{env['HTTP_CLIENT_IP'].inspect}" \
+ "HTTP_X_FORWARDED_FOR=#{env['HTTP_X_FORWARDED_FOR'].inspect}"
+ end
+
+ client_ip || forwarded_ips.last || remote_addrs.last
+ end
+
+ protected
+
+ def ips_from(header)
+ ips = @env[header] ? @env[header].strip.split(/[,\s]+/) : []
+ ips.reject{|ip| ip =~ @middleware.trusted_proxies }
+ end
end
end
-end \ No newline at end of file
+end