Module: Geocoder::Request
- Defined in:
- lib/geocoder/request.rb
Constant Summary collapse
- GEOCODER_CANDIDATE_HEADERS =
There’s a whole zoo of nonstandard headers added by various
proxy softwares to indicate original client IP.
ANY of these can be trivially spoofed!
(except REMOTE_ADDR, which should by set by your server, and is included at the end as a fallback.
Order does matter: we’re following the convention established in
ActionDispatch::RemoteIp::GetIp::calculate_ip() https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb where the forwarded_for headers, possibly containing lists, are arbitrarily preferred over headers expected to contain a single address.
['HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'HTTP_X_CLIENT_IP', 'HTTP_CLIENT_IP', 'HTTP_X_REAL_IP', 'HTTP_X_CLUSTER_CLIENT_IP', 'REMOTE_ADDR']
Instance Method Summary collapse
- #geocoder_spoofable_ip ⇒ Object
-
#location ⇒ Object
The location() method is vulnerable to trivial IP spoofing.
-
#safe_location ⇒ Object
This safe_location() protects you from trivial IP spoofing.
Instance Method Details
#geocoder_spoofable_ip ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/geocoder/request.rb', line 46 def geocoder_spoofable_ip # We could use a more sophisticated IP-guessing algorithm here, # in which we'd try to resolve the use of different headers by # different proxies. The idea is that by comparing IPs repeated # in different headers, you can sometimes decide which header # was used by a proxy further along in the chain, and thus # prefer the headers used earlier. However, the gains might not # be worth the performance tradeoff, since this method is likely # to be called on every request in a lot of applications. GEOCODER_CANDIDATE_HEADERS.each do |header| if @env.has_key? header addrs = geocoder_split_ip_addresses(@env[header]) addrs = geocoder_remove_port_from_addresses(addrs) addrs = geocoder_reject_non_ipv4_addresses(addrs) addrs = geocoder_reject_trusted_ip_addresses(addrs) return addrs.first if addrs.any? end end @env['REMOTE_ADDR'] end |
#location ⇒ Object
The location() method is vulnerable to trivial IP spoofing.
Don't use it in authorization/authentication code, or any
other security-sensitive application. Use safe_location
instead.
10 11 12 |
# File 'lib/geocoder/request.rb', line 10 def location @location ||= Geocoder.search(geocoder_spoofable_ip, ip_address: true).first end |
#safe_location ⇒ Object
This safe_location() protects you from trivial IP spoofing.
For requests that go through a proxy that you haven't
whitelisted as trusted in your Rack config, you will get the
location for the IP of the last untrusted proxy in the chain,
not the original client IP. You WILL NOT get the location
corresponding to the original client IP for any request sent
through a non-whitelisted proxy.
21 22 23 |
# File 'lib/geocoder/request.rb', line 21 def safe_location @safe_location ||= Geocoder.search(ip, ip_address: true).first end |