Class: ActionDispatch::RemoteIp::GetIp

Inherits:
Object
  • Object
show all
Defined in:
lib/action_dispatch/middleware/remote_ip.rb

Instance Method Summary collapse

Constructor Details

#initialize(env, middleware) ⇒ GetIp

Returns a new instance of GetIp.



35
36
37
38
39
# File 'lib/action_dispatch/middleware/remote_ip.rb', line 35

def initialize(env, middleware)
  @env          = env
  @middleware   = middleware
  @calculated_ip = false
end

Instance Method Details

#calculate_ipObject

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.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/action_dispatch/middleware/remote_ip.rb', line 47

def calculate_ip
  client_ip     = @env['HTTP_CLIENT_IP']
  forwarded_ips = ips_from('HTTP_X_FORWARDED_FOR')
  remote_addrs  = ips_from('REMOTE_ADDR')

  check_ip = client_ip && forwarded_ips.present? && @middleware.check_ip
  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

  not_proxy = client_ip || forwarded_ips.last || remote_addrs.first

  # Return first REMOTE_ADDR if there are no other options
  not_proxy || ips_from('REMOTE_ADDR', :allow_proxies).first
end

#to_sObject



66
67
68
69
70
# File 'lib/action_dispatch/middleware/remote_ip.rb', line 66

def to_s
  return @ip if @calculated_ip
  @calculated_ip = true
  @ip = calculate_ip
end