¿Cómo puedo detectar si el usuario está en localhost en PHP?

99

En otras palabras, ¿cómo puedo saber si la persona que usa mi aplicación web está en el servidor en el que reside? Si mal no recuerdo, PHPMyAdmin hace algo como esto por razones de seguridad.

Richie Márquez
fuente

Respuestas:

177

También puede utilizar $_SERVER['REMOTE_ADDR']la dirección IP del cliente que la solicita el servidor web.

$whitelist = array(
    '127.0.0.1',
    '::1'
);

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}
mauris
fuente
2
Lo que haría que esto fuera más fácil de romper que falsificar la IP. Realmente deberías cambiarlo.
Pekka
3
@ skcin7 podría ser la configuración de su servidor. revisalo.
mauris
4
@Pekka 웃 puede enviar, por ejemplo, Host: 127.0.0.1y se completará HTTP_HOST, por lo que no es un método confiable en absoluto.
Dejan Marjanović
4
Sí, este es un mal consejo y está en su forma actual y necesita ser editado o rechazado.
Pekka
3
No olvide IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax
26

Como complemento, como función ...

function isLocalhost($whitelist = ['127.0.0.1', '::1']) {
    return in_array($_SERVER['REMOTE_ADDR'], $whitelist);
}
Jens Törnell
fuente
5
Como buena práctica, recomendaría agregar "si no devuelve falso"; para que la función siempre devuelva un valor booleano. O alternativamente, simplemente elimine "if" por completo y en su lugar "return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);"
Joe Irby
15

Los usuarios de sistemas operativos más nuevos (Win 7, 8) también pueden encontrar necesario incluir una dirección remota con formato IPV6 en su matriz de lista blanca:

$whitelist = array('127.0.0.1', "::1");

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}
rgdigital
fuente
14

$_SERVER["REMOTE_ADDR"]debería decirle la IP del usuario. Sin embargo, es falso.

Consulte esta pregunta sobre recompensas para una discusión muy detallada.

Creo que lo que recuerdas con PHPMyAdmin es algo diferente: muchos servidores MySQL están configurados para que solo se pueda acceder a ellos desde localhost por razones de seguridad.

Pekka
fuente
Vale la pena señalar que algunos servidores MySQL están configurados al no vincularse a una interfaz pública. De manera similar, si desea restringir una aplicación PHP de la misma manera, debe considerar servirla a través de una instancia de Apache vinculada solo a una interfaz interna.
Frank Farmer
8

Lo siento, pero todas estas respuestas me parecen terribles. Sugeriría reformular la pregunta porque, en cierto sentido, todas las máquinas son "localhost".

La pregunta debería ser; ¿Cómo ejecuto diferentes rutas de código según la máquina en la que se ejecuta?

En mi opinión, la forma más fácil es crear un archivo llamado DEVMACHINE o lo que realmente quieras y luego simplemente verificar

file_exists ('DEVMACHINE')

¡Recuerde excluir este archivo cuando lo cargue en el entorno de alojamiento en vivo!

Esta solución no depende de la configuración de la red, no se puede falsificar y facilita el cambio entre ejecutar "live-code" y "dev-code".

Daniklad
fuente
6

No parece que debas usar $_SERVER['HTTP_HOST'], porque este es el valor en el encabezado http, fácilmente falsificado.

También puede usar $_SERVER["REMOTE_ADDR"], este es el valor más seguro, pero también es posible falsificar. Esta remote_addres la dirección a la que Apache devuelve el resultado.

nicola
fuente
REMOTE_ADDRes posible falsificar, sin embargo, si desea falsificarlo como 127.0.0.1o ::1, eso requiere comprometer la máquina, en lo que una falsificación REMOTE_ADDRes la menor de sus preocupaciones. Respuesta relevante - stackoverflow.com/a/5092951/3774582
Goose
1

Si desea tener una lista blanca / lista de permitidos que admita IP estáticas y nombres dinámicos .

Por ejemplo:

$whitelist = array("localhost", "127.0.0.1", "devel-pc.ds.com", "liveserver.com");
if (!isIPWhitelisted($whitelist)) die();

De esta manera, podría establecer una lista de nombres / IP que podrán (seguro) ser detectados. Los nombres dinámicos agregan más flexibilidad para acceder desde diferentes puntos.

Tiene dos opciones comunes aquí, puede establecer un nombre en su archivo de hosts local o simplemente puede usar un proveedor de nombre dinámico que se puede encontrar en cualquier lugar.

Esta función CACHES resulta porque gethostbyname es una función muy lenta.

Para este alumno he implementado esta función:

function isIPWhitelisted($whitelist = false)
{
    if ( isset($_SESSION) && isset($_SESSION['isipallowed']) )
        { return $_SESSION['isipallowed'];  }

    // This is the whitelist
    $ipchecklist = array("localhost", "127.0.0.1", "::1");
    if ($whitelist) $ipchecklist = $whitelist;

    $iplist = false;
    $isipallowed = false;

    $filename = "resolved-ip-list.txt";
    $filename = substr(md5($filename), 0, 8)."_".$filename; // Just a spoon of security or just remove this line

    if (file_exists($filename))
    {
        // If cache file has less than 1 day old use it
        if (time() - filemtime($filename) <= 60*60*24*1)
            $iplist = explode(";", file_get_contents($filename)); // Read cached resolved ips
    }

    // If file was not loaded or found -> generate ip list
    if (!$iplist)
    {
        $iplist = array(); $c=0;
        foreach ( $ipchecklist as $k => $iptoresolve )
        {
            // gethostbyname: It's a VERY SLOW function. We really need to cache the resolved ip list
            $ip = gethostbyname($iptoresolve);
            if ($ip != "") $iplist[$c] = $ip;
            $c++;
        }

        file_put_contents($filename, implode(";", $iplist));
    }

    if (in_array($_SERVER['REMOTE_ADDR'], $iplist)) // Check if the client ip is allowed
        $isipallowed = true;

    if (isset($_SESSION)) $_SESSION['isipallowed'] = $isipallowed;

    return $isipallowed;
}

Para una mayor confiabilidad, puede reemplazar $ _SERVER ['REMOTE_ADDR'] por get_ip_address () que @Pekka mencionó en su publicación como "esta pregunta de recompensa"

Heroselohim
fuente
1
No sé por qué alguien asignó una puntuación negativa a mi respuesta mientras que claramente ofrece una resolución dinámica de nombres y otros no. La resolución de DNS es lenta, por eso se requieren resoluciones de almacenamiento en caché.
Heroselohim
1

¿Qué tal comparar $_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']para determinar si el cliente está en la misma máquina que el servidor?

Eugen Wesseloh
fuente
$_SERVER['SERVER_ADDR']no siempre devuelve de manera confiable la dirección del servidor, por ejemplo, si usa balanceadores de carga, devuelve la dirección IP del balanceador de carga, creo.
Mike W
-2

Encontré una respuesta fácil.

Porque todas las unidades locales tienen C: o D: o F: ... etc.

Solo detecta si el segundo carácter es un:

if ( substr_compare(getcwd(),":",1,1) == 0)
{
echo '<script type="text/javascript">alert(" The working dir is at the local computer ")</script>';
    $client_or_server = 'client';
}
else
{
echo '<script type="text/javascript">alert(" The working dir is at the server ")</script>';
    $client_or_server = 'server';
}
Scoobeedo Cool
fuente