IP do cliente em PHP: como acertar em 2025 | Guia prático

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Caça ao IP: por que só $_SERVER['REMOTE_ADDR'] já não basta?

\n\n

Imagine: você lançou um projeto educacional incrível em PHP. Tudo voa, os usuários estão felizes. Mas aí decide adicionar logging de visitantes, geolocalização ou, digamos, proteção contra votos fraudulentos. E então — puf! — descobre que metade dos seus visitantes "únicos" tem o mesmo IP: 127.0.0.1 ou 10.0.0.1. Familiar?

\n\n

O problema de obter o IP real do cliente em PHP é um clássico que nunca perde a relevância. A pergunta no Stack Overflow acumula milhares de visualizações, e iniciantes (e não só) continuam pisando nos mesmos ancinhos. Em 2025, com Cloudflare, AWS, Nginx e uma infinidade de proxies CDN como padrão de facto, confiar apenas em $_SERVER['REMOTE_ADDR'] é como ler borra de café.

\n\n

Neste artigo, não vamos apenas dar uma função pronta. Vamos dissecar a anatomia dos headers HTTP, aprender a distinguir amigos de inimigos e escrever uma forma segura e confiável de obter o IP do visitante em PHP que não vai te decepcionar em 2025. Vamos nessa!

\n\n

REMOTE_ADDR: seu cão fiel, mas cego

\n\n

Começamos pela base. $_SERVER['REMOTE_ADDR'] é o IP de quem se conectou diretamente ao seu servidor web. Se o seu site está em um servidor dedicado sem proxy, esse é o IP do cliente. Simples e confiável.

\n\n

Mas no mundo moderno, isso é raro. Na maioria das vezes, entre o usuário e seu script PHP existe uma cadeia inteira:

\n
    \n
  • CDN (Cloudflare, Fastly)
  • \n
  • Balanceador de carga (Nginx, HAProxy)
  • \n
  • Proxy reverso (Varnish, Nginx)
  • \n
  • Hospedagem com arquitetura compartilhada
  • \n
\n\n

E aí o REMOTE_ADDR mostra o IP do último elo (por exemplo, do balanceador), não o do usuário real. Para um site educacional, é um desastre: você não conseguirá distinguir um aluno de São Paulo de um aluno de Lisboa, e o sistema antispam vai bloquear todo mundo.

\n\n

Headers HTTP: onde o IP real se esconde?

\n\n

Para transmitir o IP real do cliente, os servidores proxy adicionam headers HTTP especiais. Os mais populares em 2025 são:

\n\n

1. X-Forwarded-For (XFF)

\n

O header clássico. Pode conter uma cadeia de IPs: client_ip, proxy1_ip, proxy2_ip. O primeiro IP da lista é o cliente real. Mas tem um porém: qualquer invasor pode falsificar esse header se sua infraestrutura não o limpar.

\n\n

2. X-Real-IP

\n

O header favorito do Nginx. Contém apenas um IP — o real. Mais simples e seguro, mas não é suportado por todos os proxies.

\n\n

3. CF-Connecting-IP (Cloudflare)

\n

Header específico do Cloudflare. Se você usa a CDN deles, é a opção mais confiável. Mas só se você confia no Cloudflare (e deve, eles são bons nisso).

\n\n
\n Importante: Nunca confie nos headers X-Forwarded-For e X-Real-IP de fontes desconhecidas. Um invasor pode inserir qualquer IP, e seu sistema vai tratá-lo como real.\n
\n\n

Melhor prática 2025: proteção em camadas

\n\n

Então, o que fazer? Não podemos simplesmente pegar o primeiro IP do X-Forwarded-For — é perigoso. Mas também não podemos ignorar os proxies. A solução é uma lista branca de proxies confiáveis.

\n\n

A ideia é simples: sabemos os IPs dos nossos balanceadores e CDN. Se a requisição veio deles, confiamos nos headers. Caso contrário, usamos o REMOTE_ADDR.

\n\n

Aqui está uma classe PHP funcional que implementa essa lógica:

\n\n
<?php\n\nclass ClientIP\n{\n    /**\n     * Lista de IPs e sub-redes confiáveis (CIDR).\n     * Adicione aqui os IPs dos seus proxies, CDN, balanceadores.\n     */\n    private static array $trustedProxies = [\n        '127.0.0.1',          // localhost\n        '10.0.0.0/8',         // redes privadas\n        '172.16.0.0/12',                

Blogs

Book Recommendations