Configuração do projeto

IP real do visitante

Toda requisição para um projeto HTTP público passa primeiro pela Zenifra, que cuida do HTTPS, da proteção contra DDoS e do roteamento até a sua aplicação. Por isso, o endereço da conexão que a aplicação recebe é um endereço interno da plataforma, não o de quem fez o acesso. O IP real do visitante chega em um cabeçalho HTTP.

Onde está o IP do visitante

OrigemO que contémUsar?
Cabeçalho X-Real-IPO IP do visitante, definido pela ZenifraSim
Cabeçalho X-Forwarded-ForUma lista de endereços. O último é o IP do visitante; os anteriores podem ter sido enviados pelo próprio visitanteSó o último item
Endereço da conexão (req.socket.remoteAddress, REMOTE_ADDR)Um endereço interno da plataforma, igual para todos os visitantesNão

A Zenifra sempre sobrescreve o X-Real-IP. Mesmo que o visitante envie esse cabeçalho com outro valor, a aplicação recebe o IP de onde a requisição veio de fato.

Não use o primeiro item do X-Forwarded-For

O visitante pode mandar o seu próprio X-Forwarded-For. A Zenifra mantém o que ele enviou e acrescenta o IP real no final:

X-Forwarded-For: 1.2.3.4, 203.0.113.10
X-Real-IP: 203.0.113.10

Neste exemplo, 1.2.3.4 foi inventado pelo visitante e 203.0.113.10 é o IP real. Código que pega o primeiro item da lista pode ser enganado com um cabeçalho, o que quebra limites de requisição, bloqueios e registros de auditoria. Prefira o X-Real-IP.

Exemplos por linguagem

Em desenvolvimento local o cabeçalho não existe, por isso os exemplos usam o endereço da conexão como alternativa.

Node.js com Express

// Confia em um salto de proxy: o da Zenifra
app.set('trust proxy', 1)

app.get('/', (req, res) => {
  res.send(`Seu IP: ${req.ip}`)
})

Com trust proxy igual a 1, o req.ip usa o último item do X-Forwarded-For, que é o IP real. Não use trust proxy igual a true: nesse caso o Express usa o primeiro item, que o visitante pode inventar.

Node.js sem framework

const ip = req.headers['x-real-ip'] ?? req.socket.remoteAddress

Python

# Flask
ip = request.headers.get('X-Real-IP', request.remote_addr)

# FastAPI
ip = request.headers.get('x-real-ip', request.client.host)

# Django
ip = request.META.get('HTTP_X_REAL_IP', request.META.get('REMOTE_ADDR'))

PHP

$ip = $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'];

Go

ip := r.Header.Get("X-Real-IP")
if ip == "" {
	ip, _, _ = net.SplitHostPort(r.RemoteAddr)
}

HTTPS e porta originais

A aplicação recebe a requisição por uma conexão interna, mas a Zenifra informa como o visitante acessou:

X-Forwarded-Proto: https
X-Forwarded-Port: 443

Assim como o X-Real-IP, esses valores são definidos pela Zenifra e não podem ser trocados pelo visitante. Com o proxy configurado como confiável, os frameworks reconhecem o acesso por HTTPS e geram URLs absolutas com https:// e cookies Secure:

  • Express: com app.set('trust proxy', 1), req.protocol vale 'https' e req.secure vale true.
  • Django: SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') faz request.is_secure() retornar True.

Boas práticas

  • Guarde o IP como texto. Aceite IPv4 e IPv6, com até 45 caracteres.
  • Use o IP em limites de requisição, logs e antifraude, sempre a partir do X-Real-IP.
  • Não force HTTPS na aplicação. A Zenifra já redireciona http:// para https:// antes de a requisição chegar. Opções como SECURE_SSL_REDIRECT no Django, force_ssl no Rails ou middlewares de redirecionamento podem criar um loop.
  • Para bloquear ou liberar IPs, prefira o controle de acesso por IP do console (a partir do plano Premium Plus). Ele usa o IP real do visitante e barra o acesso antes de chegar à aplicação.
  • IP não é identidade. Várias pessoas podem dividir o mesmo IP, como em empresas e redes móveis. Mantenha login, tokens ou chaves de API nas rotas sensíveis.

Próximos passos

FAQ

Por que a minha aplicação mostra o mesmo IP para todos os visitantes?

Ela está lendo o endereço da conexão, que é interno da plataforma. Troque para o cabeçalho X-Real-IP, como nos exemplos acima.

O visitante consegue falsificar o X-Real-IP?

Não. A Zenifra substitui o valor enviado pelo visitante pelo IP de onde a requisição veio.

Funciona com domínio personalizado?

Sim. O cabeçalho chega da mesma forma no subdomínio da Zenifra e nos domínios personalizados.

Última atualização em

Nessa página