Proxy e Load balancers
Servidores proxy, balanceadores de carga e outros intermediários podem alterar a forma como uma solicitação chega à aplicação. Quando há terminação TLS no proxy ou encaminhamento por outro host, a aplicação deixa de enxergar diretamente algumas informações da conexão original:
- Se o cliente acessa o proxy por HTTPS, mas o proxy se comunica com a aplicação por HTTP (por exemplo, após terminar a conexão TLS), a aplicação enxerga HTTP na conexão recebida. Para que ela saiba que o acesso original usou HTTPS, o proxy deve informar o esquema original em um cabeçalho.
- Como a conexão chega à aplicação a partir do proxy, o endereço remoto visto pelo servidor costuma ser o IP do proxy, não o do cliente. Para obter o IP do cliente, o proxy deve encaminhá-lo em um cabeçalho, como
X-Forwarded-Forou um cabeçalho específico do provedor.
Essas informações são úteis em redirecionamentos, geração de URLs absolutas, registros de acesso, aplicação de políticas e geolocalização aproximada. Porém, um cabeçalho não é confiável só por estar presente: a aplicação deve aceitar esses valores apenas de proxies explicitamente confiáveis.
Configurando
Guia rápido para configurar o Inphinit quando a aplicação roda atrás de um load balancer ou proxy reverso.
1. Verifique quais cabeçalhos o servidor envia
Confirme quais cabeçalhos o load balancer ou proxy realmente envia à aplicação. Os nomes abaixo são convenções comuns; o conjunto disponível depende do produto e da configuração:
- X-Forwarded-For
- X-Forwarded-Proto
- X-Forwarded-Host
- X-Forwarded-Prefix
2. Determine os IPs confiáveis
Defina quais endereços IP ou redes correspondem aos proxies autorizados a fornecer esses cabeçalhos. O Inphinit só confia nos valores encaminhados quando o endereço que se conectou diretamente à aplicação estiver nessa lista:
-
IP do load balancer/proxy: use
setKnownProxies. -
Rede (CIDR) do load balancer/proxy: use
setKnownNetworks.
Exemplos:
| Tipo | Exemplo |
|---|---|
| IP único | 10.0.0.5 |
| Rede CIDR | 10.0.0.0/24 |
Segurança: qualquer cliente pode enviar cabeçalhos X-Forwarded-* falsos. Cadastre somente proxies que você conhece, evite redes amplas e, sempre que possível, bloqueie o acesso direto à aplicação (por firewall ou security group) para que ninguém contorne o proxy.
3. Habilite APP_FORWARDED
Nas variáveis de ambiente do servidor, defina:
APP_FORWARDED=1
Se estiver utilizando o arquivo .env, habilite essa variável nele.
4. Ajuste o system/main.php
Use uma das opções abaixo.
Por rede (CIDR)
$forwarded->setKnownNetworks(array(
'10.0.0.0/24',
'192.168.0.0/16'
));
Por IP (proxy)
$forwarded->setKnownProxies(array(
'10.0.0.5',
'10.0.0.6'
));
Referência rápida: provedores comuns
| Provedor | Cabeçalhos comuns | IPs confiáveis |
|---|---|---|
| Cloudflare | X-Forwarded-For, X-Forwarded-Proto, CF-Connecting-IP, CF-Visitor | Use as faixas oficiais, mantendo-as atualizadas: https://www.cloudflare.com/ips/ |
| AWS ALB/ELB | X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Port | Os IPs dos nós não são fixos. Use os CIDRs das sub-redes onde o ALB está, não a VPC inteira, e restrinja a entrada da aplicação ao security group do ALB. |
| AWS CloudFront | X-Forwarded-For, CloudFront-Forwarded-Proto, CloudFront-Viewer-Address (alguns são opcionais e precisam ser habilitados na distribuição) | Faixas publicadas em https://ip-ranges.amazonaws.com/ip-ranges.json
(serviço CLOUDFRONT_ORIGIN_FACING, os IPs que o CloudFront usa para se conectar à sua origem). O CloudFront não envia X-Forwarded-Proto; veja o exemplo na seção "Ajustando os cabeçalhos".
|
Se houver mais de um proxy na frente (ex.: Cloudflare + ALB), inclua todos os IPs/redes intermediários na lista de confiáveis. Cada proxy deve acrescentar seu valor aos cabeçalhos, ou sobrescrevê-los, e nunca repassar valores arbitrários enviados pelo cliente.
Obtendo informações
Com APP_FORWARDED habilitada, as variáveis $forwarded e $app->forwarded ficam disponíveis. Os métodos getIp(), getProto(), getHost() e getPrefix() retornam, respectivamente, o IP do cliente, o esquema original, o host original e o prefixo de caminho informado pelo proxy, de acordo com os cabeçalhos e as flags configurados. Exemplo:
$app->action('GET', '/sample', function ($app) {
$ip = $app->forwarded->getIp();
});
Se a aplicação puder rodar em ambientes diferentes, com ou sem proxy, trate os dois cenários. Sem o componente, use $_SERVER['REMOTE_ADDR'], que é o endereço de quem se conectou diretamente ao servidor:
$app->action('GET', '/sample', function ($app) {
if ($app->forwarded) {
$ip = $app->forwarded->getIp();
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
});
Para montar URLs, use sempre as constantes INPHINIT_PATH e INPHINIT_BASE_URL:
elas já refletem os valores encaminhados (esquema, host e prefixo), incluindo os cabeçalhos
personalizados definidos com $forwarded->setHeaderName(). Como host e esquema afetam as URLs absolutas,
aceite esses valores apenas de proxies confiáveis. Exemplo:
$app->action('GET', '/sample', function ($app) {
// Obtém o IP
$ip = $app->forwarded ? $app->forwarded->getIp() : $_SERVER['REMOTE_ADDR'];
// Obtém protocolo://host/prefixo/rota
$url = INPHINIT_BASE_URL . INPHINIT_PATH;
});
Ajustando os cabeçalhos
Por padrão, o componente usa X-Forwarded-For, X-Forwarded-Proto e X-Forwarded-Host. Alguns proxies usam cabeçalhos próprios ou enviam informações adicionais; nesse caso, ajuste as flags e os nomes dos cabeçalhos em main.php. O exemplo abaixo habilita também X-Forwarded-Prefix. Habilite apenas o que o proxy realmente envia:
use Inphinit\Experimental\Http\Forwarded;
$forwarded->setFlags(Forwarded::IP|Forwarded::PROTO|Forwarded::HOST|Forwarded::PREFIX);
$app->action('GET', '/', 'Home::index');
A seguir, todas as flags suportadas:
| Flag | Descrição |
|---|---|
Forwarded::IP |
O valor de $forwarded->getIp() será obtido de X-Forwarded-For
ou do cabeçalho configurado.
|
Forwarded::PROTO |
O valor de $forwarded->getProto() será obtido de X-Forwarded-Proto
ou do cabeçalho configurado.
|
Forwarded::HOST |
O valor de $forwarded->getHost() será obtido de X-Forwarded-Host
ou do cabeçalho configurado.
|
Forwarded::PREFIX |
O valor de $forwarded->getPrefix() será obtido de X-Forwarded-Prefix
ou do cabeçalho configurado.
|
Forwarded::RFC7239 |
Os valores serão obtidos do cabeçalho padronizado Forwarded (RFC 7239), que define os parâmetros for (cliente), proto (protocolo) e host (host); o RFC não define prefixo de caminho. Essa flag tem prioridade sobre as demais, então use-a apenas se o proxy enviar esse cabeçalho.
|
Proxies e provedores também podem enviar cabeçalhos específicos, como Client-Ip e CF-Connecting-IP. Como o nome varia conforme o provedor, configure-o no main.php:
use Inphinit\Experimental\Http\Forwarded;
// Customiza o cabeçalho que retorna o IP
$forwarded->setHeaderName(Forwarded::IP, 'cf-connecting-ip');
// Customiza o cabeçalho que retorna o esquema (https ou http)
$forwarded->setHeaderName(Forwarded::PROTO, 'x-url-scheme');
// Customiza o cabeçalho que retorna o host
$forwarded->setHeaderName(Forwarded::HOST, 'x-host');
$app->action('GET', '/', 'Home::index');
Exemplo para o AWS CloudFront, que informa o esquema em CloudFront-Forwarded-Proto (habilite-o na política de requisição da origem):
use Inphinit\Experimental\Http\Forwarded;
$forwarded->setHeaderName(Forwarded::PROTO, 'cloudfront-forwarded-proto');
$app->action('GET', '/', 'Home::index');