Se você usa Cloudflare com Tunnel (Argo Tunnel / cloudflared), esquece $_SERVER['REMOTE_ADDR'].
Ele vai trazer 127.0.0.1 ou IP interno do túnel. Inútil.
O IP real vem via headers.
O problema
Com Cloudflare Tunnel, o fluxo é:
Cliente → Cloudflare → Tunnel → Seu servidor
Ou seja, quem conecta no seu PHP não é o cliente, é o proxy da Cloudflare.
Resultado:
echo $_SERVER['REMOTE_ADDR'];
// 127.0.0.1 (ou IP interno)
Errado.
Headers corretos
A Cloudflare injeta alguns headers úteis:
HTTP_CF_CONNECTING_IP→ IP real do cliente (o que você quer)HTTP_X_FORWARDED_FOR→ pode ter múltiplos IPs (cadeia de proxies)HTTP_X_REAL_IP→ nem sempre presente
Solução simples e objetiva
function getRealIP()
{
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
return $_SERVER['HTTP_CF_CONNECTING_IP'];
}
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// Pode vir "IP1, IP2, IP3"
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
return trim($ips[0]);
}
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
return $_SERVER['HTTP_X_REAL_IP'];
}
return $_SERVER['REMOTE_ADDR'];
}
echo getRealIP();
Versão paranoica (validação)
Porque header pode ser spoofado fora do Cloudflare:
function getRealIP()
{
$ip = null;
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[0]);
} elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
$ip = $_SERVER['HTTP_X_REAL_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : null;
}
Segurança (importante)
Se teu servidor estiver exposto direto (sem firewall), alguém pode mandar:
X-Forwarded-For: 1.2.3.4
E pronto, te enganou.
Regra: só confie nesses headers se:
- O acesso vier exclusivamente via Cloudflare
- Ou você validar o IP de origem contra ranges da Cloudflare
Dica de produção (melhor abordagem)
Trave acesso direto:
- Firewall liberando apenas IPs da Cloudflare
- Ou rode o serviço só via
localhost(Tunnel já faz isso bem)
Assim:
Qualquer header ≈ confiável
Debug rápido
print_r($_SERVER);
Vai ver exatamente o que o Tunnel está entregando.
TL;DR
REMOTE_ADDR= lixo em ambiente com tunnel- Use
HTTP_CF_CONNECTING_IP - Fallback para
X_FORWARDED_FOR - Valide IP
- Restrinja acesso ao servidor
