45

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']
Muhd
  • 24,305
  • 22
  • 61
  • 78
gkolan
  • 1,571
  • 2
  • 20
  • 37
  • This is because you are developing on your local machine. If this code is on a server and you access the page from a client you would get the *real* IP address. – Mischa Oct 08 '10 at 05:36
  • try going to the server on your 'real' address. So don't go to 127.0.0.1, but to your 'external ip'. Don't forget to run the server to listen on that address as well! – gavit Dec 05 '15 at 12:09

9 Answers9

34

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
Mischa
  • 42,876
  • 8
  • 99
  • 111
22

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
BSB
  • 1,516
  • 13
  • 14
16

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.

Swanand
  • 12,317
  • 7
  • 45
  • 62
  • so is there a way to get the IP address of the machine that sent the request? in your example to be: 192.168.1.13 – ben Jan 05 '15 at 16:07
5

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/.......

letronje
  • 9,002
  • 9
  • 45
  • 53
5

I had to do this:

require 'socket'
Socket.ip_address_list.detect(&:ipv4_private?)&.ip_address
Mitch VanDuyn
  • 2,838
  • 1
  • 22
  • 29
  • Good tip. Though this seems to return the local IP address of my device within my WIFI network, not the public IP address of my WIFI on the internet. Local IP addresses usually start with 192.168.0. – Jan Werkhoven Mar 06 '22 at 09:49
2

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! : )

Tsvetelina Borisova
  • 417
  • 1
  • 4
  • 14
1

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.

Trevor Elwell
  • 179
  • 2
  • 4
1

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.

Jan M
  • 2,205
  • 21
  • 14
  • In that case you have to make sure the server listens on the specific interface. I tried this once and the server was listening on the loopback interface only (127.0.0.1) so my Rails application never received the request. Listening on `0.0.0.0` instead did the trick. – Daniel Rikowski Oct 01 '12 at 11:11
0

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.

Yohann
  • 800
  • 10
  • 15