HOWTO · PHP
Obtenha o endereço IP do usuário em PHP
Este tutorial demonstra como obter o endereço IP do usuário em PHP
Nesta página
Para ler o endereço de rede associado a uma solicitação PHP, comece com $_SERVER['REMOTE_ADDR']. Ele identifica o par que se conectou ao servidor web. Se houver um proxy reverso diante da aplicação, esse par pode ser o proxy, e não o visitante. Cabeçalhos da solicitação relacionados a proxies só podem ser usados quando a aplicação tem uma configuração explícita de confiança para o proxy que os fornece e valida.
Leia o endereço da conexão com $_SERVER['REMOTE_ADDR']
$_SERVER é uma superglobal do PHP que contém informações sobre o servidor e a solicitação. O elemento REMOTE_ADDR contém o endereço do par conectado ao servidor que está processando a solicitação. Em uma conexão direta, esse geralmente é o cliente que se conectou. Atrás de um balanceador de carga ou proxy reverso, normalmente será o endereço do proxy. O valor recebido pelo PHP depende da configuração do servidor web e do proxy; portanto, não o descreva como um endereço garantido do usuário final.
Em uma solicitação local, o par pode ser o endereço de loopback IPv6 ::1. Endereços de loopback se referem à máquina local; ::1 é o endereço de loopback IPv6, correspondente ao 127.0.0.1 do IPv4. O valor exato depende do servidor local e da conexão. Consulte esta explicação sobre o endereço de loopback.
O exemplo executável a seguir define um valor representativo para o servidor, tornando a consulta independente de uma solicitação real. Ele mantém display_output como false, então faz a consulta sem exibir resultados; em uma aplicação, use o valor conforme as necessidades da resposta ou do registro de logs.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
<?php
$_SERVER['REMOTE_ADDR'] = '::1';
$peerAddress = $_SERVER['REMOTE_ADDR'];
$display_output = false;
if ($display_output) {
echo "The connected peer is: " . $peerAddress . PHP_EOL;
}
?>
Em uma solicitação real, use o valor de $_SERVER['REMOTE_ADDR'] fornecido pelo servidor, em vez de atribuir um valor de exemplo. A referência do Manual do PHP sobre variáveis do servidor descreve as entradas disponíveis em $_SERVER.
Interprete cabeçalhos de proxy somente quando o proxy for confiável
O PHP pode disponibilizar cabeçalhos da solicitação como entradas de $_SERVER, por exemplo HTTP_X_FORWARDED_FOR e HTTP_CLIENT_IP. A presença deles não comprova que contenham o endereço do visitante: um cliente pode enviar seus próprios valores de cabeçalho, e um proxy pode preservá-los, acrescentar valores ou substituí-los. Em particular, HTTP_X_FORWARDED_FOR pode conter uma cadeia separada por vírgulas, e não apenas um endereço. Não selecione o primeiro valor e o considere o endereço real do cliente sem aplicar as regras de confiança documentadas para sua infraestrutura.
Use um valor encaminhado somente quando o par da conexão corresponder a um proxy em que sua aplicação confia explicitamente e esse proxy estiver configurado para remover ou validar cabeçalhos de encaminhamento enviados pelo cliente. A lista de proxies confiáveis deve corresponder à sua implantação; não copie endereços de exemplo para as configurações de produção. Se o par não for confiável, use REMOTE_ADDR. HTTP_CLIENT_IP apresenta o mesmo problema de confiança e não deve ser usado como resposta especial para conexões de internet compartilhadas.
Este trecho executável representa uma implantação em que o proxy confiável substitui X-Forwarded-For por um único endereço validado. Substitua o endereço de proxy e a política de validação de exemplo pelos valores definidos para sua infraestrutura. O trecho imprime o endereço encaminhado selecionado para esses valores representativos; ele não implementa a análise de uma cadeia com vários proxies.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
if (in_array($peerAddress, $trustedProxies, true)
&& isset($_SERVER['HTTP_X_FORWARDED_FOR'])
&& filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP) !== false) {
$clientAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$clientAddress = $peerAddress;
}
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
A documentação de filter_var() explica a função de validação usada aqui. Validar que uma string é um endereço IP não comprova que ela veio de uma fonte confiável; a verificação do par e a configuração do proxy determinam essa confiança. Se o proxy encaminhar uma cadeia, use um framework ou um código cuidadosamente revisado que percorra a cadeia de acordo com as regras exatas de proxies confiáveis da sua implantação.
Use uma expressão condicional para uma alternativa compacta
Um bloco legível de if/elseif/else costuma ser mais fácil de auditar, especialmente quando inclui uma verificação de confiança do proxy. Uma expressão condicional pode representar a mesma escolha de forma compacta, mas não torna seguro um cabeçalho não confiável. O exemplo executável a seguir verifica se o proxy é confiável e usa a mesma política, descrita acima, de endereço único substituído pelo proxy. Os valores do servidor são representativos; o exemplo imprime o endereço encaminhado selecionado.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
$forwardedAddress = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
$clientAddress = in_array($peerAddress, $trustedProxies, true)
&& filter_var($forwardedAddress, FILTER_VALIDATE_IP) !== false
? $forwardedAddress
: $peerAddress;
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
A ordem da alternativa é intencional: aceite o endereço encaminhado validado somente quando o par conectado estiver na lista de proxies confiáveis; caso contrário, mantenha o endereço do par conectado. Parênteses podem tornar mais claras as expressões condicionais aninhadas, mas um operador ternário aninhado é mais difícil de manter e não substitui as verificações de confiança. Mantenha alinhados o comportamento dos cabeçalhos do proxy e a lista de permissões da aplicação para impedir que um cliente faça o próprio cabeçalho ser tratado como entrada confiável.