nginx real_ip_header e X-Forwarded-For parece errado

51

A descrição da Wikipedia sobre o cabeçalho HTTP X-Forwarded-For é:

X-Forwarded-For: client1, proxy1, proxy2, ...

A documentação do nginx para a diretiva real_ip_header lê, em parte:

This directive sets the name of the header used for transferring the replacement IP address.
In case of X-Forwarded-For, this module uses the last ip in the X-Forwarded-For header for replacement. [Emphasis mine]

Essas duas descrições parecem estar em desacordo umas com as outras. Em nosso cenário, o cabeçalho X-Forwarded-For é exatamente como descrito - o endereço IP "real" do cliente é a entrada mais à esquerda. Da mesma forma, o comportamento do nginx é usar o direito - o maior valor - que, obviamente, é apenas um dos nossos servidores proxy.

Meu entendimento de X-Real-IP é que ele é supostamente usado para determinar o endereço IP do cliente real - não o proxy . Estou faltando alguma coisa, ou isso é um bug no nginx?

E, além disso, alguém tem alguma sugestão de como fazer com que o cabeçalho X-Real-IP exiba o valor de restante , conforme indicado pela definição de X-Forwarded-For ?

    
por Kirk Woll 22.09.2011 / 22:41

3 respostas

79

Acredito que a chave para resolver problemas de X-Forwarded-For quando vários IPs são encadeados é a opção de configuração introduzida recentemente, real_ip_recursive (adicionada no nginx 1.2.1 e 1.3.0). A partir dos docs reais nginx :

If recursive search is enabled, an original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field.

nginx estava pegando o último endereço IP na cadeia por padrão porque era o único que era considerado confiável. Mas com as novas opções real_ip_recursive ativadas e com vários set_real_ip_from , você pode definir vários proxies confiáveis e buscar o último IP não confiável.

Por exemplo, com esta configuração:

set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

E um cabeçalho X-Forwarded-For, resultando em:

X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1

O nginx agora selecionará 123.123.123.123 como o endereço IP do cliente.

Quanto ao motivo pelo qual o nginx não escolhe apenas o endereço IP mais à esquerda e exige que você defina explicitamente proxies confiáveis, é para evitar a falsificação de IP fácil.

Digamos que o endereço IP real de um cliente seja 123.123.123.123 . Digamos também que o cliente não serve para nada, e eles estão tentando imitar o endereço IP para 11.11.11.11 . Eles enviam uma solicitação para o servidor com este cabeçalho já em vigor:

X-Forwarded-For: 11.11.11.11

Como os proxies reversos simplesmente adicionam IPs a essa cadeia X-Forwarded-For, digamos que ela fique assim quando o nginx chegar a ela:

X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1

Se você simplesmente pegasse o endereço mais à esquerda, isso permitiria que o cliente falsificasse facilmente seu endereço IP. Mas com o exemplo acima, nginx config, o nginx confiará apenas nos dois últimos endereços como proxies. Isso significa que o nginx escolherá corretamente 123.123.123.123 como o endereço IP, apesar de o IP falso ser o mais à esquerda.

    
por 04.08.2012 / 00:45
10

A análise do cabeçalho X-Forwarded-For é de fato falha no módulo real_ip nginx.

len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;

for (p = ip + len - 1; p > ip; p--) {
  if (*p == ' ' || *p == ',') {
    p++;
    len -= p - ip;
    ip = p;
    break;
  }
}

Ele inicia na extremidade direita da string de cabeçalho e, assim que vê um espaço ou vírgula, pára de procurar e cola a parte à direita do espaço ou vírgula na variável IP. Então, trata-se do endereço de proxy mais recente como o endereço cliente original .

Não está tocando bem de acordo com as especificações; esse é o perigo de não ser explicitado em termos dolorosamente óbvios em uma RFC.

Além de: É difícil até mesmo encontrar uma boa fonte primária no formato, que foi originalmente definido pelo Squid - uma escavação em seus confirma a encomenda; leftmost é o cliente original, o mais à direita é o acréscimo mais recente. Estou seriamente tentado a adicionar um [citação necessário] para essa página da Wikipedia. Uma edição anônima parece ser a da Internet autoridade sobre o assunto.

Se possível, você pode fazer com que seus proxies intermediários parem de se adicionar ao final do cabeçalho, deixando apenas o endereço real do cliente apenas?

    
por 23.09.2011 / 00:08
4

X-Real-IP é o endereço IP do cliente real com o qual o servidor está falando (o cliente "real" do servidor), que, no caso de uma conexão com proxy, é o servidor proxy. É por isso que o X-Real-IP conterá o último IP no cabeçalho X-Forwarded-For.

    
por 22.09.2011 / 23:07