¿Cuál es la forma más precisa de recuperar la dirección IP correcta de un usuario en PHP?

Sé que hay una gran cantidad de$ _SERVER Encabezados de variables disponibles para la recuperación de direcciones IP. Me preguntaba si existe un consenso general sobre cómo recuperar con mayor precisión la dirección IP real de un usuario (sabiendo que ningún método es perfecto) usando dichas variables.

Pasé un tiempo tratando de encontrar una solución en profundidad y encontré el siguiente código basado en varias fuentes. Me encantaría que alguien pudiera hacer agujeros en la respuesta o arrojar algo de luz sobre algo que quizás sea más preciso.

edición incluye optimizaciones de @Alix

 /**
  * Retrieves the best guess of the client's actual IP address.
  * Takes into account numerous HTTP proxy headers due to variations
  * in how different ISPs handle IP addresses in headers between hops.
  */
 public function get_ip_address() {
  // Check for shared internet/ISP IP
  if (!empty($_SERVER['HTTP_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_CLIENT_IP']))
   return $_SERVER['HTTP_CLIENT_IP'];

  // Check for IPs passing through proxies
  if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
   // Check if multiple IP addresses exist in var
    $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    foreach ($iplist as $ip) {
     if ($this->validate_ip($ip))
      return $ip;
    }
   }
  }
  if (!empty($_SERVER['HTTP_X_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_X_FORWARDED']))
   return $_SERVER['HTTP_X_FORWARDED'];
  if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
   return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
  if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && $this->validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
   return $_SERVER['HTTP_FORWARDED_FOR'];
  if (!empty($_SERVER['HTTP_FORWARDED']) && $this->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.
  *
  * @access public
  * @param string $ip
  */
 public function validate_ip($ip) {
     if (filter_var($ip, FILTER_VALIDATE_IP, 
                         FILTER_FLAG_IPV4 | 
                         FILTER_FLAG_IPV6 |
                         FILTER_FLAG_NO_PRIV_RANGE | 
                         FILTER_FLAG_NO_RES_RANGE) === false)
         return false;
     self::$ip = $ip;
     return true;
 }
Palabras de advertencia (actualización)

REMOTE_ADDR todavía representa elmas fiable fuente de una dirección IP. El otro$_SERVER Las variables mencionadas aquí pueden ser falsificadas por un cliente remoto muy fácilmente. El propósito de esta solución es intentar determinar la dirección IP de un cliente sentado detrás de un proxy. Para sus propósitos generales, puede considerar usar esto en combinación con la dirección IP devuelta directamente desde$_SERVER['REMOTE_ADDR'] y almacenando ambos.

Para el 99,9% de los usuarios, esta solución se adaptará perfectamente a sus necesidades. No lo protegerá del 0,1% de los usuarios malintencionados que intentan abusar de su sistema inyectando sus propios encabezados de solicitud. Si confía en direcciones IP para algo de misión crítica, recurra aREMOTE_ADDR y no te molestes en atender a los que están detrás de un proxy.

Respuestas a la pregunta(10)

Su respuesta a la pregunta