Obtain client IP from PHP

4

How can I get the client's actual IP address from PHP if possible.

This means that there is a direct connection, or by means of a proxy , or router or whatever, I always identify the IP real of the client computer.

    
asked by José Miguel Sepulveda 04.05.2017 в 15:14
source

3 answers

7

I will share a PHP script that I created by researching. I use it to know the people who access an Android app that queries data on my server through a URL.

The script shows the following:

  • Customer's IP
  • Date
  • Country, City or other geographic data of the client, for this query an API called Geoplugin. With this API you can determine several geographical elements of the IP.
  • Resource to which the client has accessed. In my case I wanted to know what part of my API was being accessed. The script retrieves that data and writes it to the file.
  • Write the results in a .txt file. The output of the results can be adapted to your context, that is, file, screen printing, sending by email, etc. that will depend on what you want to do. In this specific case the data is written in a file, a kind of log of visits.

Notes:

  • This in a script with more options than you are asking, if you just want to get the IP without further, you can ignore the other parts like using Geoplugin, or obtaining the URL, etc.

  • Geoplugin is an interesting API a free webmaster resource that easily provides geolocation technology ...

    It serves to locate the IP and for other things, you can try it online, in the link.

Well, now we go with the script. I have commented some things, so it is very easy to understand:

Code:

<?php

    //Llamamos a la función, y ella hace todo :)
    write_visita ();

    //función que escribe la IP del cliente en un archivo de texto    
    function write_visita (){

        //Indicar ruta de archivo válida
        $archivo="ruta/archivo/visitas.txt";

        //Si que quiere ignorar la propia IP escribirla aquí, esto se podría automatizar
        $ip="mi.ip.";
        $new_ip=get_client_ip();

        if ($new_ip!==$ip){
            $now = new DateTime();

       //Distinguir el tipo de petición, 
       // tiene importancia en mi contexto pero no es obligatorio

        if (!$_GET) {
            $datos="*POST: ".$_POST;

        } 
        else
        {
            //Saber a qué URL se accede
            $peticion = explode('/', $_GET['PATH_INFO']);
            $datos=str_pad($peticion[0],10).' '.$peticion[1];   
        }
        $txt =  str_pad($new_ip,25). " ".
                str_pad($now->format('Y-m-d H:i:s'),25)." ".
                str_pad(ip_info($new_ip, "Country"),25)." ".json_encode($datos);

        $myfile = file_put_contents($archivo, $txt.PHP_EOL , FILE_APPEND);
        }
    }


    //Obtiene la IP del cliente
    function get_client_ip() {
        $ipaddress = '';
        if (getenv('HTTP_CLIENT_IP'))
            $ipaddress = getenv('HTTP_CLIENT_IP');
        else if(getenv('HTTP_X_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
        else if(getenv('HTTP_X_FORWARDED'))
            $ipaddress = getenv('HTTP_X_FORWARDED');
        else if(getenv('HTTP_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
        else if(getenv('HTTP_FORWARDED'))
           $ipaddress = getenv('HTTP_FORWARDED');
        else if(getenv('REMOTE_ADDR'))
            $ipaddress = getenv('REMOTE_ADDR');
        else
            $ipaddress = 'UNKNOWN';
        return $ipaddress;
    }


    //Obtiene la info de la IP del cliente desde geoplugin

    function ip_info($ip = NULL, $purpose = "location", $deep_detect = TRUE) {
        $output = NULL;
        if (filter_var($ip, FILTER_VALIDATE_IP) === FALSE) {
            $ip = $_SERVER["REMOTE_ADDR"];
            if ($deep_detect) {
                if (filter_var(@$_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP))
                    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
                if (filter_var(@$_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP))
                    $ip = $_SERVER['HTTP_CLIENT_IP'];
            }
        }
        $purpose    = str_replace(array("name", "\n", "\t", " ", "-", "_"), NULL, strtolower(trim($purpose)));
        $support    = array("country", "countrycode", "state", "region", "city", "location", "address");
        $continents = array(
            "AF" => "Africa",
            "AN" => "Antarctica",
            "AS" => "Asia",
            "EU" => "Europe",
            "OC" => "Australia (Oceania)",
            "NA" => "North America",
            "SA" => "South America"
        );
        if (filter_var($ip, FILTER_VALIDATE_IP) && in_array($purpose, $support)) {
            $ipdat = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip));
            if (@strlen(trim($ipdat->geoplugin_countryCode)) == 2) {
                switch ($purpose) {
                    case "location":
                        $output = array(
                            "city"           => @$ipdat->geoplugin_city,
                            "state"          => @$ipdat->geoplugin_regionName,
                            "country"        => @$ipdat->geoplugin_countryName,
                            "country_code"   => @$ipdat->geoplugin_countryCode,
                            "continent"      => @$continents[strtoupper($ipdat->geoplugin_continentCode)],
                            "continent_code" => @$ipdat->geoplugin_continentCode
                        );
                        break;
                    case "address":
                        $address = array($ipdat->geoplugin_countryName);
                        if (@strlen($ipdat->geoplugin_regionName) >= 1)
                            $address[] = $ipdat->geoplugin_regionName;
                        if (@strlen($ipdat->geoplugin_city) >= 1)
                            $address[] = $ipdat->geoplugin_city;
                        $output = implode(", ", array_reverse($address));
                        break;
                    case "city":
                        $output = @$ipdat->geoplugin_city;
                        break;
                    case "state":
                        $output = @$ipdat->geoplugin_regionName;
                        break;
                    case "region":
                        $output = @$ipdat->geoplugin_regionName;
                        break;
                    case "country":
                        $output = @$ipdat->geoplugin_countryName;
                        break;
                    case "countrycode":
                        $output = @$ipdat->geoplugin_countryCode;
                        break;
                }
            }
        }
        return $output;
    }

?>

Result

Part of the data written in the file:

82.24.244.140             2017-05-02 03:43:10       United Kingdom            "laudes     20170502"
89.141.58.49              2017-05-02 04:03:38       Spain                     "oficio     20170502"
80.58.131.161             2017-05-02 05:37:46       Spain                     "oficio     20170502"
186.119.11.69             2017-05-02 06:00:42       Colombia                  "laudes     20170502"
186.119.11.69             2017-05-02 06:03:17       Colombia                  "visperas   20170502"
137.101.114.197           2017-05-02 06:30:34       Spain                     "tercia     20170502"
189.163.204.25            2017-05-02 07:00:40       Mexico                    "homilias   20170502"
179.40.81.2               2017-05-02 07:06:03       Argentina                 "oficio     20170502"
176.83.200.79             2017-05-02 07:23:57       Spain                     "laudes     20170502"
190.102.58.34             2017-05-02 07:45:20       Panama                    "homilias   20170502"
170.51.58.170             2017-05-02 08:00:28       Paraguay                  "tercia     20170502"
187.134.245.128           2017-05-02 08:42:29       Mexico                    "laudes     20170502"
83.32.169.72              2017-05-02 11:48:40       Spain                     "visperas   20170502"
    
answered by 05.05.2017 / 13:35
source
2

According to your question, try this method. I hope it serves you.

<?php

    function getRealIP(){

        if (isset($_SERVER["HTTP_CLIENT_IP"])){

            return $_SERVER["HTTP_CLIENT_IP"];

        }elseif (isset($_SERVER["HTTP_X_FORWARDED_FOR"])){

            return $_SERVER["HTTP_X_FORWARDED_FOR"];

        }elseif (isset($_SERVER["HTTP_X_FORWARDED"])){

            return $_SERVER["HTTP_X_FORWARDED"];

        }elseif (isset($_SERVER["HTTP_FORWARDED_FOR"])){

            return $_SERVER["HTTP_FORWARDED_FOR"];

        }elseif (isset($_SERVER["HTTP_FORWARDED"])){

            return $_SERVER["HTTP_FORWARDED"];

        }else{

            return $_SERVER["REMOTE_ADDR"];

        }
    }       
?>
    
answered by 04.05.2017 в 15:25
2

The codes given in the answers are vulnerable to falsification (spoofing) and you have to be careful where you use it.

In simple words:

  

Obtaining the real client / user address will never be reliable.

In the answers there are several headers ( HTTP_ ) which are not known if they are established by different proxies and the problem is that with the headings HTTP can be manipulated easily:

  • curl : curl --header "X-Forwarded-For: 192.168.0.2" http://example.com
  • Chrome Extension: ModHeader

That is, for security ( eg in the authentication environment or similar ), none of these values should be used, since the client / user can modify the header X_FORWARDED_FOR or CLIENT_IP to any value, unless you have a trusted proxy .

And anyway you should validate the client / user entries since it can include dangerous statements in the HTTP header, eg: '; DROP TABLE users;--

Not being behind a proxy:

REMOTE_ADDR will give you a real IP , which will be the most reliable you can get, being the source IP of the connection TCP and can not be replaced by changing a header HTTP .

Knowing all this and taking the precautions you can obtain the IP in the following way:

function getUserIpAddress() {

    foreach ( [ 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR' ] as $key ) {

        // Comprobamos si existe la clave solicitada en el array de la variable $_SERVER 
        if ( array_key_exists( $key, $_SERVER ) ) {

            // Eliminamos los espacios blancos del inicio y final para cada clave que existe en la variable $_SERVER 
            foreach ( array_map( 'trim', explode( ',', $_SERVER[ $key ] ) ) as $ip ) {

                // Filtramos* la variable y retorna el primero que pase el filtro
                if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
                    return $ip;
                }
            }
        }
    }

    return '?'; // Retornamos '?' si no hay ninguna IP o no pase el filtro
} 

* We use the filter_var() function to filter the values with the following indications:

  • FILTER_VALIDATE_IP

      

    Valid if the value is an IP address, be it IPv4 or IPv6 .

  • FILTER_FLAG_NO_PRIV_RANGE :

      

    Fail if you try to validate any of the following private ranges   of IPv4: 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.

         

    Fail if you try to validate IPv6 addresses that start with FD or FC.

  • FILTER_FLAG_NO_RES_RANGE :

      

    Fail if any of the following IPv4 ranges are attempted   reserved: 0.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24 and 224.0.0.0/4. (types localhost / 127.0.0.1)

         

    This flag does not apply to IPv6 addresses.

Sources:

answered by 11.09.2017 в 11:32