Get real IP address in local Rails development environment - ruby-on-rails

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.

Related

How to get real ip address from user client when visit my website using rails in development mode

i want to get real ip address from user client when visit my website using rails in development mode?
but when i typing request.remote_ip, i get ip address 127.0.0.1??
how to get real ip address???
and when i try curl -H"X-Forwarded-For: 8.8.8.8" http://httpbin.org/ip, i get my real ip address but when i try implements gem https://github.com/geokit/geokit-rails to get country based ip address... my ip it's not valid?
i try this :
IpGeocoder.geocode('my.real.ip.address')
and get error like this :
Geokit::Geocoders::GeocodeError: Geokit::Geocoders::GeocodeError
but if i try ip adrress from example :
IpGeocoder.geocode('12.215.42.19')
it's works
=> Provider: hostip
Street:
City: Aurora
State: TX
Zip:
Latitude: 33.0582
Longitude: -97.5159
Country: US
Success: true
whats wrong in my ip address? i get my real ip address from "curl -H"X-Forwarded-For: 8.8.8.8" http://httpbin.org/ip"
if i wrong plase tell me, thanks
Here's an idea which may help:
Localhost
When you load the Rails server in development, you're accessing your localhost. This means that any requests made to this server are going to be treated as local connections (127.0.0.1)
You have to remember Rails is a server-side technology, which means it can only process requests as received (it has no bearing on where those requests come from). You can see a glimpse of this with the ActiveDispatch::Request middleware:
local?()
True if the request came from localhost, 127.0.0.1.
This means if you send a request to your local Rails server, it'll just treat it as a local request (127.0.0.1)
GeoLocation IP
Your Geolocation worked for your WAN IP (your remote IP) manually
The reason is because the GeoLocation API / service which the gem uses will ping a third-party server, which will either look up the DNS or other geographic locations for that IP:
From GeoKit GitHub:
IP-based location lookup utilizing hostip.info. Provide an IP address,
and get city name and latitude/longitude in return
Like any API, the response will depend on the input. The problem is that because Rails is treating your requests as local (from 12.7.0.0.1), it will only send that IP, which has no bearing on GeoLocation (it's local to your system, not the world)
JS
To get around this, you'll have to find a way to find your system's WAN IP in development, which you may be able to do with JS:
How to get client's IP address using javascript only? (see Chad Grant's answer):
<script type="application/javascript">
function getip(json){
alert(json.ip); // alerts the ip address
}
</script>
<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"></script>
I've not tested this, but hopefully it will give you an ideas as to what might be going wrong
Try using ngrok to create a tunnel to your local server.

Ruby on Rails: How to Get the Client IP Address

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

Devise gem(Ruby on Rails): The last signed_in always returns 127.0.0.1, How to get the real IP?

I want to get the real IP of my system so that I can further get the location(using geocoder gem). I am using devise gem's trackable module to get the IP of the user. When I try to geocode the IP, it fails because the last_signed_in_ip returned by devise is always 127.0.0.1. I double checked the location permissions in the browser so that doesnt seem to be an issue as it is allowed to track location there. What can be wrong?
Also, is there a better way to find out one's location (apart from tracking IP address and then geocoding it?). Can the user be asked again to allow location tracking from within the application in case he has not allowed it or isnt aware of such setting?
Appreciate all the help in advance.
Thanks
request.remote_ip will solve your problem...
it will never return you your own m/c address, instead 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
you can hardcode like this for testing purpose:
if request.remote_ip == '127.0.0.1'
# Hard coded remote address
'123.45.67.89'
else
request.remote_ip
end
If you want to return your external IP address programmatically then you need to access your app from that address.
When you visit your app at localhost, request.remote_ip will return 127.0.0.1 because that is your localhost IP address.
To get around this you can either forward your development port (normally 3000) from your router to your PC and then access your app by entering your external IP address into your browser instead of localhost (eg: 123.123.123.123:3000).
Alternatively add your external IP address to your hosts file pointing to localhost (ie: localhost 123.123.123.123) and then browse to your app via your external IP address as above.

Get Actual Remote IP in Rails?

I'm developing rails(2.3.8) application. I need to store actual client's remote IP address.
request.remote_ip returns only 127.0.0.1
but I need to store actual remote IP such as 93.43.56.77. Any ruby gems is available? or how do get that?
Try this:
request.env['REMOTE_ADDR']
If your request is coming from your development machine and the development machine is where your server is, probably you will get 127.0.0.1. But if the request is coming from another machine, this will be the IP the remote machine. However, under various conditions this may not be the real IP of the machine (machine behind proxy, using tor or other tool to hide it e.t.c.).
Your computer essentially has two network interfaces.
'93.43.56.77' which is for your network adapter which connects to the network via wireless or wire.
'127.0.0.1' which is a virtual adapter which is used when connecting to itself.
You will not get the application to show '93.43.56.77' unless the connection is running over that connection, which means it will need to be on a different computer.
If you are so concerned about it, you can easily push it up to Heroku where it should work as you expect.

How to configure http://localhost:9000 to http:/mylocal.loc

I'm using the Play Framework which uses http://localhost:9000 by default. I'm also trying something with Twitter and it needs to use a callback url for authentication, but Twitter won't accept http://localhost:9000 as a callback URL.
How can I configure my localhost to map to something like http://mylocal.loc, (similar as with an Apache vhost), instead of http://localhost:9000?
The problem is that the URL needed to be entered in the following format:
http://127.0.0.1:9000/twitter-callback
The above works perfectly as a Twitter callback address.
Twitter isn't trying to access localhost directly, it simply takes the above address as far as I understand, sticks it into the HTTP response header, prompting whichever browser being used to perform a straight forward 302 redirect.
The following blog post had some invaluable information in regards to this question:
http://www.tonyamoyal.com/2009/08/17/how-to-quickly-set-up-a-test-for-twitter-oauth-authentication-from-your-local-machine/
The reason that twitter can't use localhost as a callback url is because localhost is a redirect to your computers loopback interface. In other words, localhost is always the computer that you're on. In order for other computers (including twitter) to access your host, you need to use an external IP address, or a hostname.
To get your IP address, visit whatsmyip. This will tell you your external IP address (which other computers on the internet can access). If you have a static IP address, you can purchase a domain name, or get a free one from something like no-ip or dyndns to make it easier to remember and type. You'll need to point a DNS record from that domain to your IP. You'll also probably need to do some port forwarding and stuff to get it to go to your computer on port 9000, rather than your router (dependent on your network setup).
Possibly an easier option would be to obtain a free hosting/domain service whilst you're testing.
EDIT: josef's problem was not related to the absence of internet access to his local server, see his own answer for what was going on and a solution. This answer handles the case where a local server needs to be visible from the internet.
localhost, aka 127.0.0.1 is the name that on each computer points to the computer itself. So Twitter looks at itself, obviously doesn't see the service, end of story.
If your computer is connected to a local network, most likely that network is NATed and using private addresses like 192.168.x.x, 10.x.x.x or 172.16x.x.x. These addresses are private (not known outside of the local network because not routed on the internet), so that doesn't help you either.
What remains is your public IP address, ie the address your router gets from your ISP. Via DNS you can map that address to a name, a free service that allows you to map a fixed name also to a variable address is DynDNS.
But wait, there is more! Your router protects your network by not allowing traffic originating OUTSIDE the private network IN, unless you define some forwarding rule in the router, in your case a rule that forwards incoming tcp traffic on port 9000 to your machine's port 9000.
Once all that has been taken care of, your computer will be accessible from the outside, and your callback should work.
Edit your hosts file and add the following line:
127.0.0.1 mylocal.loc
For Windows, it is located in C:\Windows\System32\drivers\etc\. On *nix, you can find it in /etc.

Resources