Ruby on Rails: How to Get the Client IP Address - ruby-on-rails

I have searched a lot, and I could not find a solution. I tried:
Rails.logger.error request.remote_ip
Rails.logger.error request.env["REMOTE_ADDR"]
But the result is something weird: 10.130.150.254 or 10.130.150.251.
I used my cell phone's LTE/4G networking to test, and it always gave me 10.130.247.251, which is a Class A reserved private network IP address.
I also tried:
Rails.logger.error request.env["HTTP_X_FORWARDED_FOR"]
Rails.logger.error request.env["HTTP_X_REAL_IP"]
Rails.logger.error request.env["HTTP_X_CLUSTER_CLIENT_IP"]
But those gave me empty strings.
When I use my cell phone and point to touch.whatsmyip.org, it gives me: 172.56.9.89, which is a public IP address.
We use HTTPS SSL termination and a load balancer, it probably looks like "Get Remote Host Client IP Behind Load Balancers (ELB)".
How do I get the client IP address? If the client is behind a proxy, that's fine, then the proxy IP address is also good for me.
I'm using Apache and Passenger to serve the application.
"request.remote_ip" is a similar issue.

It turns out that our IT had not configured to pass it at the Load Balancer. Once he finished configuring, it works. Both request.env["HTTP_X_FORWARDED_FOR"] and request.remote_ip works.

Hope this will be helpful
env['action_dispatch.remote_ip'].calculate_ip

Related

In Rails 4, how do I configure a list of trusted proxies for RemoteIp?

My application logs the ip address of each user that logs in, but I've noticed that it's logging the IP address of our load balancer instead of the actual client ip. Researching the issue, I believe it's because our load balancers use publically routable ip addresses, and Rails is ignoring the X-Forwarded-For header assuming it's been spoofed. The solution appears to be to 'whitelist' the range of ip's used by our load balancers.
My question is, exactly how do I do that, for rails 4.1.x? Here's what I have now in config/environments/production.rb:
config.action_dispatch.custom_proxies = %r{
^100\.30 | # production environment load balancers
^200\.40 | # dev environment load balancers
}x
I tried to format it like the TRUSTED_PROXIES in remote_ip.rb, but maybe it should be a string or an array, or a differently formatted regex? Any help on the details are much appreciated. Bonus upvote if you can suggest an integration test that would catch this configuration breaking in a future version of rails. :-)
UPDATE
I've tried multiple ways to update this, and had slightly more success using config.action_dispatch.trusted_proxies. This keeps my load balancers from getting logged, but leaves all IP addresses logged as '127.0.0.1', whether they're internal or external. In logs/unicorn.log, the ip addresses are coming in as [external address, 10.* address, load balancer address], so I know the problem is at the rack or rails layer, not earlier in apache or nginx. I've also tried to replace the TRUSTED_PROXIES constant with a list that does NOT include the 10.* range (because internal users have that range), but to no apparent effect.
At this point, it looks like Rails 4.1.x is broken for any application that has real users coming from non-public IP addresses, or any application hosted in a network environment that has a load balancer with an external IP address.
As of Rails 4.2 you have to define the proxies in a different way:
config.action_dispatch.trusted_proxies = %w(100.30.0.0/16 200.40.0.0/16).
map { |proxy| IPAddr.new(proxy) }
See https://github.com/rails/rails/issues/5223#issuecomment-199082324
You can add another configutation option config.action_dispatch.ip_spoofing_check so Rails doesn't check for IP spoofing.
The option is described on the rails guide about configuration and on the ActionDispatch::RemoteIp module

Remote IP is 127.0.0.1 returned when using SSL / HTTPS

When using https, the request.remote_ip returns 127.0.0.1. This prevents geocode lookup.
Is there a way to get the correct remote IP?
I have seen a few possible workarounds:
request.env['REMOTE_ADDR']
request.env['HTTP_X_FORWARDED_FOR']
which return 10.102.1.1
request.env[‘HTTP_X_REAL_IP’]
which returns ""
It turns out this is a limitation of the way the server at ninefold is set up.
"Since our Rails stack is Apache Passenger, the client side IP headers are actually stripped off when they pass through the HA Proxy load balancer. In the CItrix implementation of this service, we are unable to pass those headers through to the rails app. At this stage its not possible to access the remote user's IP address."
As a possible work around, you could use a service like Fastly to do your load balancing, then point it directly at your app servers' IPs to bypass HAProxy on Ninefold. You'd get a nice, fast CDN in the process too.

request.remote_ip returns wrong ip

I have logging on my website, and i see logs for different people (with different UserAgent strings).
I'm sure, that they have different ip, but all the log records having the same ip.
I use request.remote_ip to store it in DB.
I don't have Apache as front-end. I just have Mongrel.
The question is - Why they are the same ?
If both users are behind the same proxy server or use the same internet provider, they may appear to have the same IP address. The IP that is seen at the web server is not the IP address of the individual PC, it's the address of the connection being used.
If you are using a load balancer, particularly a non-transparent load balancer, your server will see the IP address of the load balancer. Often times the load balancer will throw the the original remote ip address into a HTTP header.

Get real IP address in local Rails development environment

I have Rails 2.3.8, Ruby 1.8.7, Mongrel Web Server and MySQL database.
I am in the development mode and I need to find the real IP address
When I use request.remote_ip I am getting the IP as 127.0.0.1
I know I am getting 127.0.0.1 because I am developing on the local machine.. but is there a way to get the real ip-address even if I am on the local machine?
I am using these mentioned below in my controller and all I get is 127.0.0.1 with all of them in the view.
request.remote_ip
request.env["HTTP_X_FORWARDED_FOR"]
request.remote_addr
request.env['REMOTE_ADDR']
As far as I can see there is no standard method for getting the remote address of your local machine. If you need the remote address for (testing) your geocoding, I suggest adding 127.0.0.1 to your database table that matches IP addresses with locations.
As a last resort you could also hard code your remote address. E.g. like this:
class ApplicationController < ActionController::Base
def remote_ip
if request.remote_ip == '127.0.0.1'
# Hard coded remote address
'123.45.67.89'
else
request.remote_ip
end
end
end
class MyController < ApplicationController
def index
#client_ip = remote_ip()
end
end
This is what I normally do nowadays:
if Rails.env.production?
request.remote_ip
else
Net::HTTP.get(URI.parse('http://checkip.amazonaws.com/')).squish
end
I don't think you will get your 'real-ip' on localhost and the reason for this actually lies in TCP/IP.
The remote ip address depends upon the network the request is being sent to. Since it is a part of TCP/IP to send your IP address when communicating, it always translates to relative IP address that the destination computer may understand. When the request is within your subnet, it is your local IP. The moment it goes out to the network through your service provider, it assumes a global IP, which can be tracked back to the service provider (Note: this is arguable and depends on your network setup).
So if you are testing locally then it would be 127.0.0.1 as you have experienced. If you are sending it over your local network, it'll be your IP within that network. For example, my machine's IP in my office network is 192.168.1.7, and if I access my app at 3000 port through another computer in the same network, say from 192.168.1.13, then I get the request.remote_ip as 192.168.1.13
What this is means is, while you are on localhost, 127.0.0.1 is your real IP. And likewise in the example I mentioned, 192.168.1.13 is the real IP for the machine that sent the request.
Depends on how you access the url.
If you access the url using http://127.0.0.1/.... or http://localhost/.... , you'll get 127.0.0.1 as the remote ip. If you are on a LAN, use http://{lan-ip}/....
for e.g. http://172.20.25.210/.......
I had to do this:
require 'socket'
Socket.ip_address_list.detect(&:ipv4_private?)&.ip_address
I am testing with Rspec and what I did was:
request.stub(:remote_ip).and_return('198.172.43.34')
Instance.stub(:find_by_key).and_return(#instance)
before = #instance.weekly_statistic.times_opened_by['198.172.43.34']
get :key, :key=>"314C00"
#instance.weekly_statistic.times_opened_by['198.172.43.34'].should == before+1
And it worked like a charm! : )
If you access the development machine with your real IP you should get your real IP, so don't use localhost, but your use your real IP. Not all routers are will allow LAN access to a machine to an external IP address that is actually on that LAN, but most will.
Problem:
We were trying to do a similar thing for a project recently and were having trouble using request.remote_ip in our code. It kept returning 127.0.0.1 or ::1. When combined with the Geocoder gem it was giving us an empty array and was basically useless.
Solution:
There's a really nice API at telize.com which returns the IP address of whatever hits it. The code we implemented looked something like this:
location = Geocoder.search(HTTParty.get('http://www.telize.com/ip').body)
It's not the most rails-y way to do it, but I think this is a pretty good solution since it will work locally and on production as well. The only potential problem is if you hit their API limit, but for small projects this should be a non-issue.
You could use request.ip to get your real machine IP, although request.remote_ip may be a better when you want IPs of other machines.

Method to get the client ip address

I'm developing an application where it seems likely that people will attempt to hide what their client IP address is behind a proxy server.
Is there a unified way to get what the actual client IP Address is behind the proxy? Looking at the Ruby docs, it explicitly states that
request.remote_ip
and
request.remote_addr
both would return the proxy address and not the actual client IP and I'm thrown by the "may contain" descriptions in the rest of the HTTP headers.
It depends if the proxy supports X-Forwarded-For. I'd run some tests to be sure that remote_ip isn't what you're looking for - based on a quick glance at the code it attempts to read the HTTP_X_FORWARDED_FOR header.
I'm typing this from a machine that's behind a proxy. I'm not "hiding", it's how my organisation (and most others large enough to have a server) works. I don't have a fixed IP address: it's allocated dynamically. So I can't see how knowing my "current" IP address is going to help, since it'll be different tomorrow. Heck, I may be connected via a different proxy tomorrow (I work for a large organisation)!
At home, I have several machines connected through a router. Again, I don't have a fixed IP address: it's allocated dynamically by my ISP. It's a large ISP, so there's probably a proxy server somewhere upstream.
So I think what you want is not technically possible. What kind of application would make it "likely that people will attempt to hide what their client IP address is" anyway? What problem are you trying to solve?

Resources