From 93422af5d5bc0285bd72cfb2fd9b59f6d64ba141 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 3 Mar 2010 16:22:30 -0800 Subject: Move remote_ip to a middleware: * ActionController::Base.ip_spoofing_check deprecated => config.action_dispatch.ip_spoofing_check * ActionController::Base.trusted_proxies deprecated => config.action_dispatch.trusted_proxies --- actionpack/lib/action_dispatch/http/request.rb | 31 +------------ .../middleware/block_untrusted_ips.rb | 25 ----------- .../lib/action_dispatch/middleware/remote_ip.rb | 51 ++++++++++++++++++++++ actionpack/lib/action_dispatch/railtie.rb | 1 + 4 files changed, 53 insertions(+), 55 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/middleware/block_untrusted_ips.rb create mode 100644 actionpack/lib/action_dispatch/middleware/remote_ip.rb (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 7a17023ed2..56a2b9bf6a 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -119,36 +119,7 @@ module ActionDispatch # delimited list in the case of multiple chained proxies; the last # address which is not trusted is the originating IP. def remote_ip - remote_addr_list = @env['REMOTE_ADDR'] && @env['REMOTE_ADDR'].scan(/[^,\s]+/) - - unless remote_addr_list.blank? - not_trusted_addrs = remote_addr_list.reject {|addr| addr =~ TRUSTED_PROXIES || addr =~ ActionController::Base.trusted_proxies} - return not_trusted_addrs.first unless not_trusted_addrs.empty? - end - remote_ips = @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_X_FORWARDED_FOR'].split(',') - - if @env.include? 'HTTP_CLIENT_IP' - if ActionController::Base.ip_spoofing_check && remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP']) - # We don't know which came from the proxy, and which from the user - raise ActionController::ActionControllerError.new < 1 && (TRUSTED_PROXIES =~ remote_ips.last.strip || ActionController::Base.trusted_proxies =~ remote_ips.last.strip) - remote_ips.pop - end - - return remote_ips.last.strip - end - - @env['REMOTE_ADDR'] + (@env["action_dispatch.remote_ip"] || ip).to_s end # Returns the lowercase name of the HTTP server software. diff --git a/actionpack/lib/action_dispatch/middleware/block_untrusted_ips.rb b/actionpack/lib/action_dispatch/middleware/block_untrusted_ips.rb deleted file mode 100644 index 8aed0c45a6..0000000000 --- a/actionpack/lib/action_dispatch/middleware/block_untrusted_ips.rb +++ /dev/null @@ -1,25 +0,0 @@ -module ActionDispatch - class BlockUntrustedIps - class SpoofAttackError < StandardError ; end - - def initialize(app) - @app = app - end - - def call(env) - if @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_CLIENT_IP'] - remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',') - - unless remote_ips.include?(@env['HTTP_CLIENT_IP']) - http_client_ip = @env['HTTP_CLIENT_IP'].inspect - http_forwarded_for = @env['HTTP_X_FORWARDED_FOR'].inspect - - raise SpoofAttackError, "IP spoofing attack?!\n " \ - "HTTP_CLIENT_IP=#{http_client_ip}\n HTTP_X_FORWARDED_FOR=http_forwarded_for" - end - end - - @app.call(env) - end - end -end \ No newline at end of file diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb new file mode 100644 index 0000000000..c7d710b98e --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb @@ -0,0 +1,51 @@ +module ActionDispatch + class RemoteIp + class IpSpoofAttackError < StandardError ; end + + class RemoteIpGetter + def initialize(env, check_ip_spoofing, trusted_proxies) + @env = env + @check_ip_spoofing = check_ip_spoofing + @trusted_proxies = trusted_proxies + end + + def remote_addrs + @remote_addrs ||= begin + list = @env['REMOTE_ADDR'] ? @env['REMOTE_ADDR'].split(/[,\s]+/) : [] + list.reject { |addr| addr =~ @trusted_proxies } + end + end + + def to_s + return remote_addrs.first if remote_addrs.any? + + forwarded_ips = @env['HTTP_X_FORWARDED_FOR'] ? @env['HTTP_X_FORWARDED_FOR'].strip.split(/[,\s]+/) : [] + + if client_ip = @env['HTTP_CLIENT_IP'] + if @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 + return client_ip + end + + return forwarded_ips.reject { |ip| ip =~ @trusted_proxies }.last || @env["REMOTE_ADDR"] + end + end + + def initialize(app, check_ip_spoofing = true, trusted_proxies = nil) + @app = app + @check_ip_spoofing = check_ip_spoofing + regex = '(^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.)' + regex << "|(#{trusted_proxies})" if trusted_proxies + @trusted_proxies = Regexp.new(regex, "i") + end + + def call(env) + env["action_dispatch.remote_ip"] = RemoteIpGetter.new(env, @check_ip_spoofing, @trusted_proxies) + @app.call(env) + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 79e9464337..e486bd4079 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -6,6 +6,7 @@ module ActionDispatch railtie_name :action_dispatch config.action_dispatch.x_sendfile_header = "X-Sendfile" + config.action_dispatch.ip_spoofing_check = true # Prepare dispatcher callbacks and run 'prepare' callbacks initializer "action_dispatch.prepare_dispatcher" do |app| -- cgit v1.2.3