How to get an IP address using Ruby on Rails

Last Updated Jan 20, 2021
Emma Jagger

Engineer, maker, Google alumna, CMU grad

As a general rule, a website does not have to worry about its hosting infrastructure. And yet, there is a special case for which a web developer must understand the network environment around the server machine: when it is necessary to retrieve its visitors' IP address.

The task seems simple since the webserver knows its visitors' IP addresses, which can be retrieved from one of its variables. And yet, there are complications.

A simple method to retrieve the IP address using Ruby on Rails

The request object available in Rails controllers exposes many helpful methods to get information about the client's request (the visitor of your site). You can use the request.ip method to get the IP address of the visitor, and we will observe some peculiarities:


class HomeController < ApplicationController
  def index
    render plain: "You IP address is #{client_ip}"
  end

  private def client_ip
    request.ip
  end
end

Obviously, if you run this code on your local machine, and depending on its configuration, the page will display "Your IP address is 127.0.0.1" or "Your IP address is ::1". The first case corresponds to a IPv4 address, and the second to a IPv6 address. The two addresses have in common that they are both a loopback addresses, which are used by any computer to connect to itself.

To get a more interesting result, you have to deploy your code on a public server at a hosting company. Once this is done, get your real public IP address using a third party service as a reference. You can find such a service on Google. Then access your site to compare the results. If everything went well, your script would show you the same IP address as the one given by the third party service.

Why is it necessary to know the infrastructure of your hosting provider?

As a web developer, you may have already heard of load-balancer, DDoS mitigator, or more simply proxy or firewall. You may not have bothered until now to understand how they work. But to get the IP address of your visitors, you will need to understand some of the basic mechanisms.

A proxy or firewall is positioned between your web server and your visitor. Its role is to protect your web server, which is certainly configured only to accept connections that have been filtered by the proxy.

In such a configuration, if you run the script we wrote above, you will get an address that doesn't match your IP address, and if you search a little deeper, you will quickly understand that it corresponds to the IP address of the proxy. Indeed, the proxy modifies the client request to make your server believe that it is the request's origin. The proxy thus ensures that all communications pass through it.

In this case, you will have to use the remote_ip method, which is also available in the controllers, verifying that the IP address has been changed by a proxy and returning the client's real address. Here is how to modify your script:


class HomeController < ApplicationController
  def index
    render plain: "You IP address is #{client_ip}"
  end

  private def client_ip
    request.remote_ip
  end
end

From now, if you connect to your server, you will see your real IP address.

How to know if the visitor connects through a VPN using Ruby on Rails

If you connect to the Internet through a VPN service and access your IP address detection script, you will find that the address displayed is not your real address but the VPN's exit address.

Since VPN is a service to protect Internet users, they make sure to prevent websites from discovering their users' real IP address. As a result, your script won't determine if the user is behind a VPN server or not, and therefore it will be impossible for you to know if the IP address thus obtained is real.

Detect if a user is using a VPN service

To do this, it is necessary to use a service that analyzes the IP addresses of your visitors and determines, among other things, whether this address corresponds to an exit address of a VPN service. You may be able to develop such a service by yourself, but you would have to update the list of VPNs' list of known IPs constantly, which is extremely time-consuming.

Abstract provides such a service for free, responding very fast and always up to date, through the geolocation API. Just create an account in a few seconds, which gets you your private API key. Then a simple HTTP call allows you to determine if the visitor is behind a VPN.


class HomeController < ApplicationController
  def index
    string = "You IP address is #{client_ip}"
    if behind_vpn?
      string << " and you are using a VPN"
    end

    render plain: string
  end

  private
  def client_ip
    request.remote_ip
  end

  def behind_vpn?
    uri = URI('https://ipgeolocation.abstractapi.com/v1/?api_key=#{api_key}&ip_address=#{client_ip}')

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER

    request =  Net::HTTP::Get.new(uri)
    response = JSON.parse(http.request(request))

    ! response['security']['is_vpn']
  end
end

Abstract's IP Geolocation API makes it easy to geolocate IP addresses in Ruby on Rails. Try it for free today.
Get started