IP del cliente en PHP: cómo no equivocarse en 2025

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué «simplemente REMOTE_ADDR» ya no funciona

Cada desarrollador de PHP se ha preguntado al menos una vez: «¿Cómo obtener la dirección IP del cliente?». En Stack Overflow, este tema acumula cientos de miles de visitas, y debajo de la respuesta canónica hay docenas de comentarios aclaratorios. El problema es que en 2025, el simple $_SERVER['REMOTE_ADDR'] ya no es suficiente.

Los sitios web modernos funcionan detrás de CDN (Cloudflare, Akamai), balanceadores de carga y servidores proxy. Los usuarios se conectan a través de VPN o Tor. Y los atacantes han aprendido a falsificar las cabeceras. Si desea conocer la dirección IP real del visitante — y al mismo tiempo no abrir la puerta a ataques — debe aplicar prácticas probadas.

En este artículo, mostraré cómo funciona la determinación de IP en PHP, analizaré los escollos y proporcionaré código listo para usar que puede utilizar con confianza en 2025.



¿Cómo «ve» PHP la dirección IP?

Cuando el navegador envía una solicitud al servidor, PHP llena automáticamente el array superglobal $_SERVER. La clave REMOTE_ADDR es la responsable de la dirección IP del «interlocutor». En un mundo ideal (sin proxy), esta es la IP del cliente:

<?php$ip = $_SERVER['REMOTE_ADDR']; // 192.168.1.5?>

Pero en la realidad, a menudo detrás del servidor hay nginx, HAProxy o Cloudflare. Entonces, REMOTE_ADDR muestra la IP del proxy, no la del usuario. La dirección real se transmite en las cabeceras HTTP:

  • HTTP_X_FORWARDED_FOR — cabecera estándar para proxies;
  • HTTP_X_REAL_IP — utilizado por nginx;
  • HTTP_CF_CONNECTING_IP — específico de Cloudflare;
  • HTTP_CLIENT_IP — raro, pero ocurre.

El problema: cualquiera de estas cabeceras puede ser falsificada. Si confía en $_SERVER['HTTP_X_FORWARDED_FOR'] sin verificación, un atacante puede fácilmente suplantar una IP ajena.



REMOTE_ADDR vs X-Forwarded-For: ¿cuándo usar qué?

Aquí está la regla clave que le salvará de dolores de cabeza:

  • Si el sitio está directamente en el servidor sin proxy — use solo REMOTE_ADDR.
  • Si el sitio está detrás de un proxy de confianza (CDN, balanceador) — tome la IP de la cabecera, pero solo después de verificar que la solicitud proviene precisamente de su proxy.

En 2025, el estándar de facto es X-Forwarded-For. Dentro de él puede haber una cadena de IPs: cliente, proxy1, proxy2. La primera dirección es la del cliente, la última es la dirección del último proxy.



¿Por qué no se puede confiar ciegamente en X-Forwarded-For?

Imagine: un atacante envía una solicitud con la cabecera X-Forwarded-For: 127.0.0.1. Si su código simplemente lee $_SERVER['HTTP_X_FORWARDED_FOR'], obtendrá 127.0.0.1 (localhost). Los registros, la analítica, la geolocalización — todo se romperá. Peor aún, el atacante puede suplantar la IP de otro usuario para hacerse pasar por él.

Solución: confiar en la cabecera X-Forwarded-For solo si REMOTE_ADDR es igual a la IP de su proxy de confianza. De ninguna otra manera.



Mejor práctica 2025: función universal para obtener la IP

He recopilado una lógica probada que tiene en cuenta todas las realidades modernas. La función:

  1. Verifica si la solicitud pasa a través de proxies de confianza (usted define su lista).
  2. Si es así — extrae la primera IP de X-Forwarded-For.
  3. Si no — devuelve REMOTE_ADDR.
  4. Filtra direcciones privadas y reservadas (opcional).
<?php/** * Obtiene la dirección IP real del cliente. *  * @param array $trustedProxies Lista de IPs de proxy de confianza * @return string Dirección IP o '0.0.0.0' si no se pudo determinar */function getClientIP(array $trustedProxies = []): string {    $remoteAddr = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';                

Blogs

Book Recommendations