Home » Php » php – Retrieve real IP of user using codeigniter

php – Retrieve real IP of user using codeigniter

Posted by: admin July 12, 2020 Leave a comment

Questions:

My app tracks the IP address of users logging into the site. The tracking was working fine on a regular web server (we were on hostgator) but seemed to start tracking odd IP addresses when we switch to a PaaS platform (pagodabox) After speaking to pagodabox support they informed me that the IPs codeigniter was picking up was the IPs of the load balancers/routers of pagodabox and to get a user’s actual IP address I would have to utilize HTTP_X_FORWARDED_FOR

I was using codeigniter’s input class function $this->input->ip_address() to retreive the user’s IP. I looked at the function and noticed they had some sort of features to retreive the HTTP_X_FORWARDED_FOR IP value but I am not sure how to use it. Do i have to change/add something in the config?

EDIT: After a few users have pointed out where I should add in the list of IP addresses of load balancers a new question came up: What would I do if the list of IP’s change frequently? (ie no static IP, all dynamic)

How to&Answers:

I’m sure you’ve resolved this by now, but I thought I would post the correct answer for future reference. I came across this same problem (Using load balancers on AWS with a CodeIgniter app.) As you pointed out, it’s easy enough to get the correct IP behind a load balancer or other distributed environment using the HTTP_X_FORWARDED_FOR header. The problem is how do we correctly implement this solution in CodeIgniter? As the previous answer points out: Write your own IP function. The problem with this, is what if ip_address() is called throughout your app? Wouldn’t it be better to override that function (With one that looks at the correct header)? CodeIgniter has a convenient mechanism for this, which is handy:

The solution is to extend the CodeIgniter Input class, by creating a new class file in /application/core called MY_Input.php (MY_ is a configurable prefix for extensions, you can change it in your config file). With extensions, you can create a function of the SAME name as the original class method without breaking anything, and without editing core files. CodeIgniter will just use your new method instead. Your extended input class will look something like this:

class MY_Input extends CI_Input {

    function __construct()
    {
        parent::__construct();
    }
    //Overide ip_address() with your own function
    function ip_address() 
    {
        //Obtain the IP address however you'd like, you may want to do additional validation, etc..
        $correct_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];  
        return $correct_ip_address;
    }
}

This way we’ve changed the core behavior without hacking the framework, and existing calls to ip_address() throughout your app will now be using your method.

With regards to dealing with other IP’s in the chain, if you’re only interested in the client IP, it shouldn’t matter. With AWS load balancers at least, the HTTP_X_FORWARDED_FOR header seems to always contain the correct client IP.

Answer:

Oliver’s solution works, but in some circumstances, it is better to use the following if you know the proxy IP addresses that are in use. Edit your application/config/config.php file to include the following:

$config['proxy_ips'] = '1.2.3.4, 2.3.4.5';

Also be aware of the fact that the header information is usually unreliable and should not be used for security sensitive purposes. For example, it is not uncommon to restrict admin users to use only some white listed IP addresses.

Answer:

<?php 
function getIPfromXForwarded() 
{ 
    $ipString = @getenv("HTTP_X_FORWARDED_FOR"); 
    $addr     = explode(",",$ipString); 

    return $addr[sizeof($addr)-1]; 
} 
?> 

Try something like that. See if it works. Usage:

<? echo getIPfromXForwarded(); ?>

Answer:

In your case, you can add specified Load-Balancer IP into $config['proxy_ips'] (application/config/config.php), for example:

$config['proxy_ips'] = ['192.168.1.2'];

Dynamic proxy IP:

According to your dynamic IP problem, you can mask the IP range for the Load-Balancer network, for example:

 $config['proxy_ips'] = '192.168.1.0/24';

The mask function is able in Codeigniter 3


Get IP method:

$this->input->ip_address();

While $this refers to CI instance.

This method takes into account the $config[‘proxy_ips’] setting and will return the reported HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP, HTTP_X_CLIENT_IP or HTTP_X_CLUSTER_CLIENT_IP address for the allowed IP addresses.

Answer:

I came across a version of Thava’s solution that works great for situations where the load balancer IPs can change (such as AWS) and still leverages CIs configuration files natively. When you know you are running behind an LB you can modify config.php to be:

$config['proxy_ips'] = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '';

Knowing that REMOTE_ADDR will always be the current LB.

Thanks to Eric Brown here https://expressionengine.com/forums/archive/topic/185751/amazon-load-balancing-and-codeigniter-configproxy_ips#925678

Answer:

I know there is a good answer which is relevant to your question and is accepted by you but for future users I am sharing a function which is working perfectly for me in all situations.

 public function ip()
    {
        $ipaddress = '';
        if ($_SERVER['HTTP_CLIENT_IP'])
            $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
        else if($_SERVER['HTTP_X_FORWARDED_FOR'])
            $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
        else if($_SERVER['HTTP_X_FORWARDED'])
            $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
        else if($_SERVER['HTTP_FORWARDED_FOR'])
            $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
        else if($_SERVER['HTTP_FORWARDED'])
            $ipaddress = $_SERVER['HTTP_FORWARDED'];
        else if($_SERVER['REMOTE_ADDR'])
            $ipaddress = $_SERVER['REMOTE_ADDR'];
        else
            $ipaddress = 'UNKNOWN';
        echo $ipaddress ;
     }

Answer:

I had the same kind of situation at work, except that the IPs were not really ‘dynamic’, but the the ‘infrastructure people’ managing proxyies and load balancers used to change them for undisclosed reasons. So we had to negotiate and we came up with a solution setting up a hook in their configuration/provision management tool to write a config file somewhere (in a folder accessible to the user running our Apache/PHP).

So I used a CI hook to read that file on system bootstrap in order to change my apps config, updating values like the proxy IP list, cache path, cookie domain etc.