CloudFlare y registro de direcciones IP de visitantes a través de PHP


82

Estoy tratando de rastrear y registrar a los usuarios / visitantes que acceden a mi sitio web usando PHP $_SERVER['REMOTE_ADDR']para hacerlo. Un método típico para el seguimiento de direcciones IP en PHP.

Sin embargo, estoy usando CloudFlare para almacenar en caché y recibir sus direcciones IP como las de CloudFlare:

108.162.212. * - 108.162.239. *

¿Cuál sería un método correcto para recuperar la dirección IP de los usuarios / visitantes reales sin dejar de usar CloudFlare?

Respuestas:


239

Las variables de servidor adicionales que están disponibles para Cloud Flare son:

$_SERVER["HTTP_CF_CONNECTING_IP"] dirección IP de visitante real, esto es lo que quieres

$_SERVER["HTTP_CF_IPCOUNTRY"] país del visitante

$_SERVER["HTTP_CF_RAY"]

$_SERVER["HTTP_CF_VISITOR"] esto puede ayudarlo a saber si es http o https

puedes usarlo así:

if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
  $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}

Si hace esto, y la validez de la dirección IP de visita es importante, es posible que deba verificar que $_SERVER["REMOTE_ADDR"]contiene una dirección IP de nube real válida, ya que cualquiera puede falsificar el encabezado si pudo conectarse directamente a la IP del servidor.


15
+1 para reemplazar REMOTE_ADDR con la IP real, por lo que no se requieren otras modificaciones en el código.
aalaap

11
Si la seguridad es importante, se debe verificar si la solicitud proviene de un rango de IP de Cloudflare ( cloudflare.com/ips ). Como, por ejemplo, en este Joomla! Complemento
Florian Fida

Cloudflare también tiene este código en su sitio. support.cloudflare.com/hc/en-us/articles/…
C0nw0nk

La mejor respuesta, pero también felicitaciones por incluir HTTP_CF_IPCOUNTRY, no me había encontrado con esa antes.
David Bell

http_cf_connecting_ip a veces da cosas como: 2a01: 6500: a043: 33a6: b36a: 7259: 4de5: 2500 alguna idea de por qué?
Michael

15

Actualización : CloudFlare ha lanzado un módulo mod_cloudflarepara apache, el módulo registrará y mostrará las direcciones IP reales de los visitantes en lugar de las a las que accede cloudflare. https://www.cloudflare.com/resources-downloads#mod_cloudflare (Respuesta de: olimortimer )

Si no tiene acceso al tiempo de ejecución de apache, puede usar el siguiente script, esto le permitirá verificar si la conexión fue a través de cloudflare y obtener la ip de los usuarios.

Estoy reescribiendo mi respuesta que usé para otra pregunta " Identificador de IP directo / DNS de CloudFlare "

Las ips de Cloudflare se almacenan en público para que pueda verlas aquí y luego verificar si la ip es de cloudflare (esto nos permitirá obtener la ip real del encabezado http HTTP_CF_CONNECTING_IP).

Si está usando esto para deshabilitar todas las conexiones que no sean de cf o viceversa, le recomiendo que tenga un único archivo de script php que se llame antes que cualquier otro script, como common.php o pagestart.php, etc.

function ip_in_range($ip, $range) {
    if (strpos($range, '/') == false)
        $range .= '/32';

    // $range is in IP/CIDR format eg 127.0.0.1/24
    list($range, $netmask) = explode('/', $range, 2);
    $range_decimal = ip2long($range);
    $ip_decimal = ip2long($ip);
    $wildcard_decimal = pow(2, (32 - $netmask)) - 1;
    $netmask_decimal = ~ $wildcard_decimal;
    return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal));
}

function _cloudflare_CheckIP($ip) {
    $cf_ips = array(
        '199.27.128.0/21',
        '173.245.48.0/20',
        '103.21.244.0/22',
        '103.22.200.0/22',
        '103.31.4.0/22',
        '141.101.64.0/18',
        '108.162.192.0/18',
        '190.93.240.0/20',
        '188.114.96.0/20',
        '197.234.240.0/22',
        '198.41.128.0/17',
        '162.158.0.0/15',
        '104.16.0.0/12',
    );
    $is_cf_ip = false;
    foreach ($cf_ips as $cf_ip) {
        if (ip_in_range($ip, $cf_ip)) {
            $is_cf_ip = true;
            break;
        }
    } return $is_cf_ip;
}

function _cloudflare_Requests_Check() {
    $flag = true;

    if(!isset($_SERVER['HTTP_CF_CONNECTING_IP']))   $flag = false;
    if(!isset($_SERVER['HTTP_CF_IPCOUNTRY']))       $flag = false;
    if(!isset($_SERVER['HTTP_CF_RAY']))             $flag = false;
    if(!isset($_SERVER['HTTP_CF_VISITOR']))         $flag = false;
    return $flag;
}

function isCloudflare() {
    $ipCheck        = _cloudflare_CheckIP($_SERVER['REMOTE_ADDR']);
    $requestCheck   = _cloudflare_Requests_Check();
    return ($ipCheck && $requestCheck);
}

// Use when handling ip's
function getRequestIP() {
    $check = isCloudflare();

    if($check) {
        return $_SERVER['HTTP_CF_CONNECTING_IP'];
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

Usar el script es bastante simple:

$ip = getRequestIP();
$cf = isCloudflare();

if($cf) echo "Connection is through cloudflare: <br>";
else    echo "Connection is not through cloudflare: <br>";

echo "Your actual ip address is: ". $ip;
echo "The server remote address header is: ". $_SERVER['REMOTE_ADDR'];

Este script le mostrará la dirección IP real y si la solicitud es CF o no.


Esta es la respuesta correcta, sin embargo, tenga en cuenta que debe seguir actualizando las IP con regularidad. Los actuales en el código anterior ya no son válidos y, por lo tanto, el código fallará. Puede obtener las últimas IP aquí: cloudflare.com/ips Idealmente, debería almacenarlas en un archivo para que solo tenga que actualizar el archivo externo o, mejor aún, obtenerlas
rafark

11

Desde que se hizo y respondió esta pregunta, CloudFlare ha lanzado mod_cloudflarepara Apache, que registra y muestra la dirección IP real del visitante en lugar de la dirección de CloudFlare:

https://www.cloudflare.com/resources-downloads#mod_cloudflare


2019: ya no son compatibles mod_cloudflare, pero se pueden usar. Hay algo nuevo llamado mod_remoteip. Referencia: support.cloudflare.com/hc/en-us/articles/…
sinaza

@sinaza probablemente sea mejor para crear una nueva respuesta, ya que mi respuesta mod_cloudflarefue de hace 4 años
olimortimer

@sjagr en lo que respecta a sus ediciones, son incorrectas: CloudFlare es en realidad Cloudflare, como publiqué originalmente
olimortimer

10

Cloudflare envía algunos encabezados de solicitud adicionales a su servidor, incluidos los CF-Connecting-IPque podemos almacenar $user_ip, si se definen, utilizando este sencillo resumen:

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

El problema con esto es que es solo un encabezado simple, por lo que cualquiera puede configurarlo en la IP que desee, lo cual es una gran vulnerabilidad de seguridad.
Rafark

@rafark No si su servidor está configurado correctamente y detrás de Cloudflare.
Sainan

Sí, por supuesto. Esta es una buena solución per se, pero aún se deben realizar verificaciones antes de usar HTTP_CF_CONNECTING_IP, como en la respuesta de Callum
rafark

@rafark También estoy de acuerdo, pero esa es una gran cantidad de código PHP que ya está presente en otra forma en su configuración de Apache (espero) y este código es más para permitir una depuración fácil y si un atacante tiene acceso a su entorno de depuración, creo tiene problemas más importantes que tratar.
Sainan

2

Sería difícil convertir HTTP_CF_CONNECTING_IP a REMOTE_ADDR. Entonces puede usar apache (.htaccess) auto anteponiendo para hacer eso. Para que no tenga que pensar si $_SERVER['REMOTE_ADDR']tiene el valor correcto en todos los scripts PHP.

.htaccess código

php_value auto_prepend_file "/path/to/file.php"

código php (file.php)

<?php

define('CLIENT_IP', isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR']);

Más información aquí


1

HTTP_CF_CONNECTING_IP solo funciona si está usando cloudflare, tal vez transfiera su sitio o elimine cloudflare, olvidará el valor, así que use este código.

$ip=$_SERVER["HTTP_CF_CONNECTING_IP"];
if (!isset($ip)) {
  $ip = $_SERVER['REMOTE_ADDR'];
}


0

Cuando usa CloudFlare, todas sus solicitudes entre su servidor y los usuarios se enrutan a través de los servidores de CloudFlare.

En este caso, existen dos métodos para obtener la dirección IP real del usuario:

  1. A través de encabezados de servidor adicionales agregados por servidores CloudFlare
  2. Agregar un módulo CloudFlare Apache / NGINX en su servidor.

Método 1: obtener IP a través de encabezados de servidor adicionales

Puede utilizar el siguiente código para obtener la dirección IP del usuario:

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) $_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

¿Cómo está funcionando?

CloudFlare agrega algunas variables de servidor adicionales en la solicitud de la siguiente manera:

$_SERVER["HTTP_CF_CONNECTING_IP"] - Dirección IP real del usuario

$_SERVER["HTTP_CF_IPCOUNTRY"] - País ISO2 del usuario

$_SERVER["HTTP_CF_RAY"] Una cadena especial para fines de registro

En el código anterior, estamos verificando si $_SERVER["HTTP_CF_CONNECTING_IP"]está configurado o no. Si está allí, consideraremos que como dirección IP del usuario, de lo contrario, usaremos el código predeterminado como$_SERVER['REMOTE_ADDR']

Método 2: Instalación del módulo Cloudflare en su servidor

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.