Cómo obtener la dirección IP del cliente en PHP

¿Cómo puedo obtener la dirección IP del cliente usando PHP?

Quiero mantener un registro del usuario que inició sesión en mi sitio web a través de su dirección IP.

preguntado el 09 de junio de 10 a las 02:06

Consulte RFC6302 para obtener recomendaciones sobre qué registrar, y específicamente hoy en día recuerde registrar el puerto y no solo la dirección. -

Una advertencia para los usuarios de rastreo, en varias regiones del mundo, los ISPS están usando CGNAT, lo que hace que sea mucho más complicado confiar en una mera dirección IP.

function getUserIpAddr () {if (! empty ($ _ SERVER ['HTTP_CLIENT_IP'])) {$ ip = $ _SERVER ['HTTP_CLIENT_IP']; } elseif (! empty ($ _ SERVER ['HTTP_X_FORWARDED_FOR'])) {$ ip = $ _SERVER ['HTTP_X_FORWARDED_FOR']; } más {$ ip = $ _SERVER ['REMOTE_ADDR']; } return $ ip; } -

Deberías usar Detección de IP abstracta. El valor es que le permitirá saber si la IP está detrás de un proxy o una VPN, lo cual creo que es importante. Tienen un fragmento de PHP desde el que puede copiar su solicitud. -

30 Respuestas

Hagas lo que hagas, asegúrate de no confiar en los datos enviados por el cliente. $_SERVER['REMOTE_ADDR'] contiene la dirección IP real de la parte que se conecta. Ese es el valor más confiable que puede encontrar.

Sin embargo, pueden estar detrás de un servidor proxy, en cuyo caso el proxy puede haber configurado la $_SERVER['HTTP_X_FORWARDED_FOR'], pero este valor se falsifica fácilmente. Por ejemplo, puede ser configurado por alguien sin un proxy, o la IP puede ser una IP interna de la LAN detrás del proxy.

Esto significa que si va a guardar el $_SERVER['HTTP_X_FORWARDED_FOR'], Asegúrese Además, salva el $_SERVER['REMOTE_ADDR'] valor. Por ejemplo, guardando ambos valores en diferentes campos de su base de datos.

Si va a guardar la IP en una base de datos como una cadena, asegúrese de tener espacio para al menos 45 caracteres. IPv6 está aquí para quedarse y esas direcciones son más grandes que las direcciones IPv4 más antiguas.

(Tenga en cuenta que IPv6 suele utilizar 39 caracteres como máximo, pero también hay un Notación IPv6 para direcciones IPv4 que en su forma completa puede tener hasta 45 caracteres. Entonces, si sabe lo que está haciendo, puede usar 39 caracteres, pero si solo desea configurarlo y olvidarlo, use 45).

respondido 21 nov., 13:20

¡Buena respuesta! Ya estoy usando $ _SERVER ['REMOTE_ADDR'] para mi servidor, y me gusta que hayas incluido otra forma, además de las ventajas y desventajas. - Azul

Nota: REMOTE_ADDR podría no contienen la IP real de la conexión TCP. Esto depende enteramente de su SAPI. Asegúrese de que su SAPI esté correctamente configurado de manera que $_SERVER['REMOTE_ADDR'] realmente devuelve la IP de la conexión TCP. De lo contrario, podría dar lugar a algunas vulnerabilidades graves, por ejemplo, StackExchange solía otorgar acceso de administrador comprobando REMOTE_ADDR para ver si coincide con "localhost", desafortunadamente la configuración de SAPI ..................................... ...................................... - marcapasos

.................................................. ........................ tenía una vulnerabilidad (se necesita HTTP_X_FORWARDED_FOR como entrada) que permite a los no administradores obtener acceso de administrador modificando el HTTP_X_FORWARDED_FOR encabezamiento. Ver también blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html - marcapasos

Qué es $_SERVER['HTTP_CLIENT_IP']) ? - montón

@chiragpatel Sí, lo hace. De lo contrario, tiene una configuración de servidor muy rota. - Emil Vikström

$_SERVER['REMOTE_ADDR'] Es posible que en realidad no contenga direcciones IP de clientes reales, ya que le proporcionará una dirección de proxy para los clientes conectados a través de un proxy, por ejemplo. Sin embargo, eso puede ser lo que realmente quieras, dependiendo de lo que hagas con las IP. Es posible que la dirección RFC1918 privada de alguien no te sirva de nada si, por ejemplo, intentas ver de dónde se origina el tráfico o recuerdas desde qué IP se conectó el usuario por última vez, dónde podría estar más la IP pública del proxy o la puerta de enlace NAT. apropiado para almacenar.

Hay varios encabezados HTTP como X-Forwarded-For que pueden o no ser establecidos por varios proxies. El problema es que son simplemente encabezados HTTP que cualquiera puede configurar. No hay garantía sobre su contenido. $_SERVER['REMOTE_ADDR'] es la dirección IP física real desde la que el servidor web recibió la conexión y a la que se enviará la respuesta. Cualquier otra cosa es solo información arbitraria y voluntaria. Solo hay un escenario en el que puede confiar en esta información: está controlando el proxy que establece este encabezado. Es decir, solo si sabe al 100% dónde y cómo se configuró el encabezado, debe prestarle atención a cualquier cosa de importancia.

Habiendo dicho eso, aquí hay un código de muestra:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Nota del editor: El uso del código anterior tiene implicaciones de seguridad. El cliente puede configurar toda la información del encabezado HTTP (es decir. $_SERVER['HTTP_...) a cualquier valor arbitrario que desee. Como tal, es mucho más confiable de usar $_SERVER['REMOTE_ADDR'], ya que el usuario no puede configurarlo.

De: http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html

Respondido el 14 de enero de 16 a las 12:01

¡NO use el código anterior a menos que sepa EXACTAMENTE lo que hace! He visto agujeros de seguridad MASIVOS debido a esto. El cliente puede configurar el X-Forwarded-For o Client-IP encabezado a cualquier valor arbitrario que desee. A menos que tenga un proxy inverso de confianza, no debe utilizar ninguno de esos valores. - Janos Pasztor

Con respecto al comentario de Janoszen, una opción es filter_var de PHP ($ _ SERVER ['REMOTE_ADDR'], FILTER_VALIDATE_IP). - filosofo perdido

X-Forwarded-For puede contener varias direcciones IP, separadas por una coma; y realmente debería ser "analizado" en lugar de tomarse al pie de la letra (AFAIK, casi nunca contiene una sola IP). - Martín Tournoij

@lostphilosopher es algo razonable y lo hará más confiable, pero desafortunadamente aún permitiría la suplantación de identidad. - tim seguine

Para un sitio de tamaño escalado, habrá balanceadores de carga y / o proxies inversos frente a los servidores de aplicaciones web. Debe configurar estos equilibradores de carga o proxies para eliminar cualquier encabezado X-Fordered-For externo y, en su lugar, insertar la suya propia de la dirección IP que ven para el cliente que se conecta. - Jon Watte

Respondido el 09 de junio de 10 a las 05:06

@Anup Prakash Esto es todo, de ahí el "REMOTO" (desde la perspectiva del guión). - artefacto

Recibo esto cuando uso tu código: ::1 - Si8

Porque estás en localhost;) - ussama dahnin

@ SiKni8 ::1 es el equivalente IPv6 de 127.0.0.1 - Camilo Martín

@CamiloMartin me acabas de enseñar algo. ¡frio! - Kristian

Aquí hay una muestra de código más limpia de una buena manera de obtener la dirección IP del usuario.

$ip = $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP'] : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);

Aquí hay una versión más corta que usa el operador elvis:

$_SERVER['HTTP_CLIENT_IP'] ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? : $_SERVER['REMOTE_ADDR']);

Aquí hay una versión que usa isset para eliminar avisos (gracias, @shasi kanth):

$ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];

respondido 02 mar '19, 23:03

Recuerde siempre desinfectar cualquier entrada que pueda haber sido modificada por el usuario. Éste es uno de esos momentos. - jose123a123

Creo que al código le falta alguna expresión y el orden de prioridades está invertido, por lo que debería ser así: $ip = $_SERVER['HTTP_CLIENT_IP']?$_SERVER['HTTP_CLIENT_IP']:($_SERVER['HTTP_X_FORWARDED_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR']); Sin embargo, muy buena. - davidtaubmann

Buena atrapada. He ajustado la publicación. ¡Gracias! - jose123a123

Acabo de agregar isset () para eliminar los avisos: $ ip = isset ($ _ SERVER ['HTTP_CLIENT_IP'])? $ _ SERVER ['HTTP_CLIENT_IP']: isset ($ _ SERVER ['HTTP_X_FORWARDE‌ D_FOR'])? $ _ SERVER ['HTTP_X_FORWARDED_FOR']: $ _ SERVER ['REMOTE_ADDR ; - shasi kanth

Como señaló alguien, los tres ejemplos ESTÁN LLENOS DE CARACTERES OCULTOS (U + 200C y U + 200B). No los pegue en su script php o obtendrá PARSE ERRORS. Si desea ver todos los caracteres ocultos, pegue esas líneas aquí: soscisurvey.de/tools/view-chars.php . ¡Limpia ese código! - Frank

Debe estar contenido en el $_SERVER['REMOTE_ADDR'] variable.

respondido 07 mar '13, 07:03

Mi solución favorita es la forma en que se usa Zend Framework 2. También considera el $_SERVER de propiedades HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP, REMOTE_ADDR pero declara una clase para que configure algunos proxies confiables y devuelve una dirección IP, no una matriz. Creo que esta es la solución que más se le acerca:

class RemoteAddress
{
    /**
     * Whether to use proxy addresses or not.
     *
     * As default this setting is disabled - IP address is mostly needed to increase
     * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
     * just for more flexibility, but if user uses proxy to connect to trusted services
     * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
     *
     * @var bool
     */
    protected $useProxy = false;

    /**
     * List of trusted proxy IP addresses
     *
     * @var array
     */
    protected $trustedProxies = array();

    /**
     * HTTP header to introspect for proxies
     *
     * @var string
     */
    protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';

    // [...]

    /**
     * Returns client IP address.
     *
     * @return string IP address.
     */
    public function getIpAddress()
    {
        $ip = $this->getIpAddressFromProxy();
        if ($ip) {
            return $ip;
        }

        // direct IP address
        if (isset($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    /**
     * Attempt to get the IP address for a proxied client
     *
     * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
     * @return false|string
     */
    protected function getIpAddressFromProxy()
    {
        if (!$this->useProxy
            || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
        ) {
            return false;
        }

        $header = $this->proxyHeader;
        if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
            return false;
        }

        // Extract IPs
        $ips = explode(',', $_SERVER[$header]);
        // trim, so we can compare against trusted proxies properly
        $ips = array_map('trim', $ips);
        // remove trusted proxy IPs
        $ips = array_diff($ips, $this->trustedProxies);

        // Any left?
        if (empty($ips)) {
            return false;
        }

        // Since we've removed any known, trusted proxy servers, the right-most
        // address represents the first IP we do not know about -- i.e., we do
        // not know if it is a proxy server, or a client. As such, we treat it
        // as the originating IP.
        // @see http://en.wikipedia.org/wiki/X-Forwarded-For
        $ip = array_pop($ips);
        return $ip;
    }

    // [...]
}

Vea el código completo aquí: https://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php

respondido 05 mar '19, 08:03

¡Gran respuesta! Usar código probado en producción, desarrollado y utilizado en un marco tan grande es una de las mejores cosas que puede hacer :) - jnhghy - Alexandru Jantea

Así que espera, ¿Zend no filtra nada? Debería ver algo como: filter_var ($ _SERVER ['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); - MH

@Hanoncs, ¿por qué harías eso? es muy difícil falsificar la dirección remota - Marius.C

@Hanoncs Creo que debes verificar el valor después de obtenerlo con esta clase. No es parte de su lógica. Simplemente obtiene el valor de $_SERVER variable como es y salta sobre algunos servidores proxy definidos y conocidos. Eso es todo. Si cree que el valor devuelto no es seguro, verifíquelo o informe un error a los desarrolladores de PHP. - algoritmo

@algorhythm ¿Cómo se determina qué es un servidor proxy conocido? - nu everest

Hay diferentes tipos de usuarios detrás de Internet, por lo que queremos capturar la dirección IP de diferentes partes. Esos son:

1. $_SERVER['REMOTE_ADDR'] - Contiene la dirección IP real del cliente. Ese es el valor más confiable que puede encontrar del usuario.

2. $_SERVER['REMOTE_HOST'] - Esto buscará el nombre de host desde el que el usuario está viendo la página actual. Pero para que este script funcione, se deben configurar las búsquedas de nombres de host dentro de httpd.conf.

3. $_SERVER['HTTP_CLIENT_IP'] - Esto buscará la dirección IP cuando el usuario sea de servicios de Internet compartidos.

4. $_SERVER['HTTP_X_FORWARDED_FOR'] - Esto obtendrá la dirección IP del usuario cuando esté detrás del proxy.

Entonces, podemos usar esta siguiente función combinada para obtener la dirección IP real de los usuarios que están viendo en diferentes posiciones,

// Function to get the user IP address
function getUserIP() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

Respondido 13 Feb 19, 16:02

Realmente fácil de falsificar. Intenté en mi propio sitio web con la extensión Requestly Chrome configurando el encabezado Client-ip en "111.111.111.111". - usuario5147563

El siguiente es el método más avanzado que he encontrado y ya probé otros en el pasado. Es válido asegurarse de obtener la dirección IP de un visitante (pero tenga en cuenta que cualquier pirata informático podría falsificar la dirección IP fácilmente).

function get_ip_address() {

    // Check for shared Internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

    // Check for IP addresses passing through proxies
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

        // Check if multiple IP addresses exist in var
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
            $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            foreach ($iplist as $ip) {
                if (validate_ip($ip))
                    return $ip;
            }
        }
        else {
            if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
        return $_SERVER['HTTP_X_FORWARDED'];
    if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
        return $_SERVER['HTTP_FORWARDED_FOR'];
    if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
        return $_SERVER['HTTP_FORWARDED'];

    // Return unreliable IP address since all else failed
    return $_SERVER['REMOTE_ADDR'];
}

/**
 * Ensures an IP address is both a valid IP address and does not fall within
 * a private network range.
 */
function validate_ip($ip) {

    if (strtolower($ip) === 'unknown')
        return false;

    // Generate IPv4 network address
    $ip = ip2long($ip);

    // If the IP address is set and not equivalent to 255.255.255.255
    if ($ip !== false && $ip !== -1) {
        // Make sure to get unsigned long representation of IP address
        // due to discrepancies between 32 and 64 bit OSes and
        // signed numbers (ints default to signed in PHP)
        $ip = sprintf('%u', $ip);

        // Do private network range checking
        if ($ip >= 0 && $ip <= 50331647)
            return false;
        if ($ip >= 167772160 && $ip <= 184549375)
            return false;
        if ($ip >= 2130706432 && $ip <= 2147483647)
            return false;
        if ($ip >= 2851995648 && $ip <= 2852061183)
            return false;
        if ($ip >= 2886729728 && $ip <= 2887778303)
            return false;
        if ($ip >= 3221225984 && $ip <= 3221226239)
            return false;
        if ($ip >= 3232235520 && $ip <= 3232301055)
            return false;
        if ($ip >= 4294967040)
            return false;
    }
    return true;
}

Respondido 01 Abr '19, 15:04

Esto está mal. HTTP_CLIENT_IP es menos confiable que REMOTE_ADDR y la función de validación de ip es una tontería. - tobltobs

@tobltobs. Es gracioso que diga esto, pero este es el único conjunto de funciones que realmente funcionó para mí detrás de un cuadro de barniz en una carga de página de redireccionamiento. Le doy un gran pulgar hacia arriba. - mike q

El vínculo está (efectivamente) roto. - Pedro Mortensen

enlace eliminado, parece que la página desapareció. gracias - manuelbcd

¿Es la mejor forma de conseguir la ip en 2019? - Fabiano Lothor

La respuesta es usar $_SERVER variable. Por ejemplo, $_SERVER["REMOTE_ADDR"] devolvería la dirección IP del cliente.

Respondido el 17 de diciembre de 13 a las 04:12

Una solución rápida (sin errores)

function getClientIP():string
{
    $keys=array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR');
    foreach($keys as $k)
    {
        if (!empty($_SERVER[$k]) && filter_var($_SERVER[$k], FILTER_VALIDATE_IP))
        {
            return $_SERVER[$k];
        }
    }
    return "UNKNOWN";
}

Respondido el 14 de diciembre de 20 a las 16:12

advertencia, los piratas informáticos pueden falsificar fácilmente la IP enviando mensajes falsos X-FORWARDED-FOR: fakeip Encabezados HTTP - Hanshenrik

Por supuesto, pero si usa NGINX, clientIP generalmente está en "HTTP_X_FORWARDED_FOR" - Stergios Zg.

Es posible que esto no funcione como esperaba: 1. Todos los encabezados aquí permiten el uso de comas y / o punto y coma, por lo que debe tokenizar la cadena (es decir, strtok($k, ';,')); 2) HTTP_X_FORWARDED no existe; 3. El uso de HTTP_FORWARDED aquí (estandarizado) siempre fallará la prueba filter_var porque usa su propia sintaxis (es decir, for=1.1.1.1;by=1.1.1.0). - Jonathan rosa

Me gusta este codenippet:

function getClientIP() {

    if (isset($_SERVER)) {

        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
            return $_SERVER["HTTP_X_FORWARDED_FOR"];

        if (isset($_SERVER["HTTP_CLIENT_IP"]))
            return $_SERVER["HTTP_CLIENT_IP"];

        return $_SERVER["REMOTE_ADDR"];
    }

    if (getenv('HTTP_X_FORWARDED_FOR'))
        return getenv('HTTP_X_FORWARDED_FOR');

    if (getenv('HTTP_CLIENT_IP'))
        return getenv('HTTP_CLIENT_IP');

    return getenv('REMOTE_ADDR');
}

Respondido 09 Abr '14, 18:04

quiero decir cuál es el punto ... no getenv darte lo mismo que $_SERVER ? - marcapasos

@Paceriermy supongo que serían versiones anteriores de PHP donde $ _SERVER aún no estaba disponible;) - mavelo

@Johan ¿Por qué no devolver una matriz con los tres? - nu everest

@nueverest Porque un usuario no accede a su sitio desde 3 IP diferentes (normalmente). Quieres devolver el que le corresponda. - pila desbordada

Como todos los demás dijeron antes, puedes usar $_SERVER['REMOTE_ADDR']; para obtener la dirección IP del cliente.

Además, si necesita más información sobre un usuario, puede usar esto:

<?php
    $ip = '0.0.0.0';
    $ip = $_SERVER['REMOTE_ADDR'];
    $clientDetails = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
    echo "You're logged in from: <b>" . $clientDetails->country . "</b>";
?>

La información más específica del cliente va en $ clientDetails.
Puede obtener elementos JSON almacenados en la variable $ clientDetails de esta manera: $ clientDetails-> PostalCode / hostname / region / loc ...

Estoy usando ipinfo.io para obtener información adicional.

Respondido 13 Feb 19, 16:02

$ip = "";

if (!empty($_SERVER["HTTP_CLIENT_IP"]))
{
    // Check for IP address from shared Internet
    $ip = $_SERVER["HTTP_CLIENT_IP"];
}
elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
    // Check for the proxy user
    $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else
{
    $ip = $_SERVER["REMOTE_ADDR"];
}
echo $ip;

Respondido 13 Feb 19, 16:02

¿Cómo devuelve el primer fragmento la dirección IP del cliente? Me parece que se hará eco de la dirección del servidor. - Robin Kanters

Gracias Robin. Sí, a veces no obtendrá el resultado correcto. Utilice una segunda solución. - mahfuz ahmed

@MahfuzAhmed, ¿puedes decir qué hace file_get_contents ()? y cómo se obtiene la IP a través de file_get_contents () - Daksh B

file_get_contents es completamente inútil aquí :) - Maciej Paprocki

¿Cuál fue la necesidad de inicializar? $ip en la línea 1. Si todas las condiciones fallan, entonces también $ip = $_SERVER['REMOTE_ADDR'] correría. - Yash Kumar Verma

Este es el método que utilizo y valida un IPv4 entrada:

// Get user IP address
if ( isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}

$ip = filter_var($ip, FILTER_VALIDATE_IP);
$ip = ($ip === false) ? '0.0.0.0' : $ip;

Respondido 09 Abr '14, 18:04

¡Gracias por permitirme falsificar mi dirección IP simplemente configurando un encabezado HTTP! - deceze ♦

Bueno, esto se puede hacer simplemente usando el GLOBAL variable nombrada como $_SERVER.

El $_SERVER es una matriz que tiene el nombre de atributo REMOTE_ADDR.

Simplemente asígnelo así:

$userIp = $_SERVER['REMOTE_ADDR'];

O utilícelo directamente como echo $_SERVER['REMOTE_ADDR']; or echo ($_SERVER['REMOTE_ADDR']);.

Respondido 13 Feb 19, 16:02

Aquí hay un poco de código que debería elegir una IP válida comprobando varias fuentes.

Primero, verifica si 'REMOTE_ADDR' es una IP pública o no (y no uno de sus proxies inversos confiables), luego pasa por uno de los encabezados HTTP hasta que encuentra una IP pública y la devuelve. (PHP 5.2+)

Debe ser confiable siempre que el proxy inverso sea confiable o el servidor esté conectado directamente con el cliente.

//Get client's IP or null if nothing looks valid
function ip_get($allow_private = false)
{
  //Place your trusted proxy server IPs here.
  $proxy_ip = ['127.0.0.1'];

  //The header to look for (Make sure to pick the one that your trusted reverse proxy is sending or else you can get spoofed)
  $header = 'HTTP_X_FORWARDED_FOR'; //HTTP_CLIENT_IP, HTTP_X_FORWARDED, HTTP_FORWARDED_FOR, HTTP_FORWARDED

  //If 'REMOTE_ADDR' seems to be a valid client IP, use it.
  if(ip_check($_SERVER['REMOTE_ADDR'], $allow_private, $proxy_ip)) return $_SERVER['REMOTE_ADDR'];

  if(isset($_SERVER[$header]))
  {
    //Split comma separated values [1] in the header and traverse the proxy chain backwards.
    //[1] https://en.wikipedia.org/wiki/X-Forwarded-For#Format
    $chain = array_reverse(preg_split('/\s*,\s*/', $_SERVER[$header]));
    foreach($chain as $ip) if(ip_check($ip, $allow_private, $proxy_ip)) return $ip;
  }

   return null;
}

//Check for valid IP. If 'allow_private' flag is set to truthy, it allows private IP ranges as valid client IP as well. (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
//Pass your trusted reverse proxy IPs as $proxy_ip to exclude them from being valid.
function ip_check($ip, $allow_private = false, $proxy_ip = [])
{
  if(!is_string($ip) || is_array($proxy_ip) && in_array($ip, $proxy_ip)) return false;
  $filter_flag = FILTER_FLAG_NO_RES_RANGE;

  if(!$allow_private)
  {
    //Disallow loopback IP range which doesn't get filtered via 'FILTER_FLAG_NO_PRIV_RANGE' [1]
    //[1] https://www.php.net/manual/en/filter.filters.validate.php
    if(preg_match('/^127\.$/', $ip)) return false;
    $filter_flag |= FILTER_FLAG_NO_PRIV_RANGE;
  }

  return filter_var($ip, FILTER_VALIDATE_IP, $filter_flag) !== false;
}

respondido 03 nov., 19:16

No entiendo por qué alguien desperdiciaría tanto tiempo escribiendo comentarios inútiles en lugar de hacer que su código sea legible. - Buffalo

function get_client_ip()
{
    foreach (array(
                'HTTP_CLIENT_IP',
                'HTTP_X_FORWARDED_FOR',
                'HTTP_X_FORWARDED',
                'HTTP_X_CLUSTER_CLIENT_IP',
                'HTTP_FORWARDED_FOR',
                'HTTP_FORWARDED',
                'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER)) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                $ip = trim($ip);
                if ((bool) filter_var($ip, FILTER_VALIDATE_IP,
                                FILTER_FLAG_IPV4 |
                                FILTER_FLAG_NO_PRIV_RANGE |
                                FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
    }
    return null;
}

O la versión comprimida:

function get_ip() {
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                    return $ip;
                }
            }
        }
    }
}

contestado el 20 de mayo de 19 a las 14:05

Uno de estos :

    $ip = $_SERVER['REMOTE_ADDR'];
    $ip = $_SERVER['HTTP_CLIENT_IP'];
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    $ip = $_SERVER['HTTP_X_FORWARDED'];
    $ip = $_SERVER['HTTP_FORWARDED_FOR'];
    $ip = $_SERVER['HTTP_FORWARDED'];

Respondido el 11 de junio de 19 a las 11:06

Documentación sobre variables de servidor: php.net/manual/es/reservado.variables.servidor.php - Jsowa

La siguiente función determina todas las posibilidades y devuelve los valores en un formato separado por comas (ip, ip, etc.).

También tiene una función de validación opcional como (primer parámetro que está deshabilitado por defecto) para validar la dirección IP contra (rango privado y rango reservado).

<?php
echo GetClientIP(true);

function GetClientIP($validate = False) {
  $ipkeys = array(
  'REMOTE_ADDR',
  'HTTP_CLIENT_IP',
  'HTTP_X_FORWARDED_FOR',
  'HTTP_X_FORWARDED',
  'HTTP_FORWARDED_FOR',
  'HTTP_FORWARDED',
  'HTTP_X_CLUSTER_CLIENT_IP'
  );

  /*
  Now we check each key against $_SERVER if containing such value
  */
  $ip = array();
  foreach ($ipkeys as $keyword) {
    if (isset($_SERVER[$keyword])) {
      if ($validate) {
        if (ValidatePublicIP($_SERVER[$keyword])) {
          $ip[] = $_SERVER[$keyword];
        }
      }
      else{
        $ip[] = $_SERVER[$keyword];
      }
    }
  }

  $ip = ( empty($ip) ? 'Unknown' : implode(", ", $ip) );
  return $ip;
}

function ValidatePublicIP($ip){
  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    return true;
  }
  else {
    return false;
  }
}

Respondido 13 Feb 19, 16:02

Prueba este:

 $_SERVER['REMOTE_ADDR'];

Respondido 13 Feb 19, 16:02

Esto ya se mencionó varias veces y su respuesta no suma nada útil. - Kenorb

'tu respuesta no suma nada útil' - no estoy seguro de lo que quieres decir, responde la pregunta que se hizo. ¿cómo no es eso útil? - Chris

porque está respondiendo a una pregunta de 5 años y ya se han respondido muchas respuestas iguales y mucho mejores. - Mg Thar

@ gyanendra-prasad-panigrahi intenta incluir enlaces útiles como documentación de funciones en Tu respuesta. - Hector

Fragmento seguro y con advertencias para obtener la dirección IP:

$ip = filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP', FILTER_VALIDATE_IP)
    ?: filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR', FILTER_VALIDATE_IP)
    ?: $_SERVER['REMOTE_ADDR']
    ?? '0.0.0.0'; // Or other value fits "not defined" in your logic

Respondido 13 Feb 19, 15:02

Esta función es compacta y puede usarla en todas partes. ¡Pero!

¡No olvides esto! En este tipo de funciones o bloques de código no hay garantía para registrar la dirección IP real del usuario porque algunos usuarios pueden usar un proxy u otra puerta de enlace segura para ser invisibles o no poder rastrear

Función PHP:

function GetIP()
{
    if ( getenv("HTTP_CLIENT_IP") ) {
        $ip = getenv("HTTP_CLIENT_IP");
    } elseif ( getenv("HTTP_X_FORWARDED_FOR") ) {
        $ip = getenv("HTTP_X_FORWARDED_FOR");
        if ( strstr($ip, ',') ) {
            $tmp = explode(',', $ip);
            $ip = trim($tmp[0]);
        }
    } else {
        $ip = getenv("REMOTE_ADDR");
    }
    return $ip;
}

Uso:

$IP = GetIP(); o directamente GetIP();

Respondido 13 Feb 19, 16:02

Esta función debería funcionar como se esperaba

function Get_User_Ip()
{
    $IP = false;
    if (getenv('HTTP_CLIENT_IP'))
    {
        $IP = getenv('HTTP_CLIENT_IP');
    }
    else if(getenv('HTTP_X_FORWARDED_FOR'))
    {
        $IP = getenv('HTTP_X_FORWARDED_FOR');
    }
    else if(getenv('HTTP_X_FORWARDED'))
    {
        $IP = getenv('HTTP_X_FORWARDED');
    }
    else if(getenv('HTTP_FORWARDED_FOR'))
    {
        $IP = getenv('HTTP_FORWARDED_FOR');
    }
    else if(getenv('HTTP_FORWARDED'))
    {
        $IP = getenv('HTTP_FORWARDED');
    }
    else if(getenv('REMOTE_ADDR'))
    {
        $IP = getenv('REMOTE_ADDR');
    }

    //If HTTP_X_FORWARDED_FOR == server ip
    if((($IP) && ($IP == getenv('SERVER_ADDR')) && (getenv('REMOTE_ADDR')) || (!filter_var($IP, FILTER_VALIDATE_IP))))
    {
        $IP = getenv('REMOTE_ADDR');
    }

    if($IP)
    {
        if(!filter_var($IP, FILTER_VALIDATE_IP))
        {
            $IP = false;
        }
    }
    else
    {
        $IP = false;
    }
    return $IP;
}

respondido 01 mar '19, 06:03

Aquí hay un trazador de líneas simple

$ip = $_SERVER['HTTP_X_FORWARDED_FOR']?: $_SERVER['HTTP_CLIENT_IP']?: $_SERVER['REMOTE_ADDR'];

EDIT:

El código anterior puede volver direcciones reservadas (como 10.0.0.1), un lista de direcciones de todos los servidores proxy en camino, etc. Para manejar estos casos use el siguiente código:

function valid_ip($ip) {
    // for list of reserved IP addresses, see https://en.wikipedia.org/wiki/Reserved_IP_addresses
    return $ip && substr($ip, 0, 4) != '127.' && substr($ip, 0, 4) != '127.' && substr($ip, 0, 3) != '10.' && substr($ip, 0, 2) != '0.' ? $ip : false;
}

function get_client_ip() {
    // using explode to get only client ip from list of forwarders. see https://en.wikipedia.org/wiki/X-Forwarded-For
    return
    @$_SERVER['HTTP_X_FORWARDED_FOR'] ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2)[0] :
    @$_SERVER['HTTP_CLIENT_IP'] ? explode(',', $_SERVER['HTTP_CLIENT_IP'], 2)[0] :
    valid_ip(@$_SERVER['REMOTE_ADDR']) ?:
    'UNKNOWN';
}

echo get_client_ip();

respondido 17 nov., 16:10

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;
} 

respondido 26 nov., 16:10

Aquí está la versión de una sola línea que obtiene la dirección IP del cliente:

$ip = @$_SERVER['HTTP_CLIENT_IP'] ?: @$_SERVER['HTTP_X_FORWARDED_FOR'] ?: @$_SERVER['REMOTE_ADDR'];

Notas

  • Mediante el uso @, suprime los avisos de PHP.
  • Valor de HTTP_X_FORWARDED_FOR puede constar de varias direcciones separadas por comas, por lo que si prefiere obtener la primera, puede utilizar el siguiente método:

    current(explode(',', @$_SERVER['HTTP_X_FORWARDED_FOR']))
    

respondido 06 mar '18, 18:03

// Function to get the client ip address
function get_ip() 
{

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;


}

Respondido 01 Abr '19, 08:04

Solo en esto, y me sorprende que aún no se haya mencionado, es obtener las direcciones IP correctas de esos sitios que se encuentran detrás de la infraestructura de CloudFlare. Romperá sus direcciones IP y les dará a todas el mismo valor. Afortunadamente, también tienen algunos encabezados de servidor disponibles. En lugar de que yo reescriba lo que ya se ha escrito, eche un vistazo aquí para obtener una respuesta más concisa, y sí, también pasé por este proceso hace mucho tiempo. https://stackoverflow.com/a/14985633/1190051

Respondido 29 Abr '19, 05:04

$_SERVER['REMOTE_ADDR'];

Ejemplo:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

contestado el 23 de mayo de 16 a las 07:05

Me pregunto por qué hay tantos votos negativos. Encontré la respuesta, aunque no es la mejor (porque no considera las redes internas como los servidores de equilibrio de carga, bastante útil y la documentación proporcionada en el contexto. Supongo que algunas personas solo quieren una solución que funcione sin cuestionar más, - Crafter

¿Te gusta lo siguiente?

if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', validate_ip)) === false or empty($ip)) {
    exit;
}
echo $ip;

PS

if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE)) === false) {
    header('HTTP/1.0 400 Bad Request');
    exit;
}

Todos los encabezados que comienzan con 'HTTP_' o 'X-' pueden falsificarse, respectivamente, lo define el usuario. Si desea realizar un seguimiento, utilice cookies, etc.

respondido 02 mar '19, 23:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.