Verifique o verniz ACL via X-Forwarded-For quando estiver atrás de um ou mais proxies (!) reversos

2

Eu tenho o Varnish rodando atrás de um proxy reverso (rodando em localhost, para descarregamento de SSL). O proxy define o cabeçalho X-Forwarded-For ou se adiciona a ele se o cabeçalho já existir.

Quando faço verificações de ACL, claro, quero verificar o IP do cliente original, não o IP do meu proxy, por isso não posso usar o campo client.ip . Com o std vmod, posso fazer o seguinte:

vcl 4.0;
import std;
sub vcl_recv {
    if (std.ip(regsub(req.http.X-Forwarded-For, ", 127.0.0.1$", ""), "0.0.0.0") ~ my_acl) {
        ...do stuff...
    }
}

Em outras palavras, eu aparei o IP do proxy (127.0.0.1) do cabeçalho antes de executá-lo através de std.ip e compará-lo à minha ACL. Isso funciona bem, exceto ...

Isso falha quando o cabeçalho X-Forwarded-For já está definido antes de chegar ao meu proxy. Nesse caso, o cabeçalho XFF contém três ou mais endereços IP. Aparar o último ainda deixa mais de um e std.ip engasga com isso, atrasando o pedido por vários segundos e, é claro, não checando o ACL.

Eu preciso ter certeza de que o cabeçalho XFF contém apenas um IP (IPv4 ou IPv6) depois que eu cortar o proxy. Este deve ser o IP do cliente.

Por exemplo:

X-Forwarded-For: 10.10.1.1, 10.10.2.2, 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1

deve se tornar

X-Forwarded-For: 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1

Como não posso confiar em nenhum cabeçalho XFF que venha de fora, gostaria de descartar tudo, menos o ip do cliente que o meu proxy viu. Meu proxy não suporta a modificação do cabeçalho XFF, então eu preciso fazê-lo em verniz.

O primeiro ponto no fluxo do verniz quando posso interagir com os cabeçalhos é em vcl_recv() e nesse ponto o verniz já adicionou o client.ip ao final da lista.

Eu esperava usar uma expressão regular para capturar os dois últimos itens (IPv4 ou IPv6) em um grupo de captura numerado ($ 1) e simplesmente substituir o cabeçalho pelo grupo de captura. Assim:

vcl 4.0;
import std;
sub vcl_recv {
    set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "([a-f0-9:.]+, [a-f0-9:.]+)$", "");
}

O terceiro argumento (a string que substitui os caracteres correspondidos pelo regex) não funciona. O cabeçalho resultante é exatamente o mesmo de antes, embora o regex capture apenas os últimos dois endereços IP.

Como posso jogar fora tudo menos os dois últimos endereços IP do cabeçalho XFF?

    
por Martijn Heemels 23.02.2017 / 18:22

1 resposta

1

Seu regex parece bem. A única coisa que vejo é que você pede para substituir o grupo por si mesmo.

Ele deve funcionar se você adicionar ^(.*) no início de sua regex e substituir o segundo argumento por

set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "");

}

Dito isto, não acho que seja uma boa ideia alterar o cabeçalho XFF. Deve ser mais padrão adicionar um cabeçalho em vez de alterar a exclusão de informações que foram transmitidas por proxies intermediários.

    
por 26.02.2017 / 08:35