Load Balancer - Verniz - Nginx

2

Estou coçando a cabeça há algumas horas e queria ver se alguém pode ajudar.

1) Eu tenho um balanceador de carga com 6 servidores no back-end.

2) Os servidores back-end são Nginx e para obter os endereços IP reais dos visitantes, tudo o que tenho que fazer é o seguinte em cada instalação do Nginx e eu consigo obter o endereço IP do cliente real de cada visitante. / p>

 set_real_ip_from 192.168.255.0/24; <-- to handle the load balancer IP
 real_ip_header X-Forwarded-For;

3) Agora eu instalei o Varnish na frente de cada Nginx rodando no 127.0.0.1 fazendo cache e por algum motivo agora o Nginx não vê mais os endereços Ip do cliente real vindo do LoadBalancer - > Verniz - > Nginx

Está imprimindo o seguinte:

endereço IP: 192.168.255.9 < - este deve ser o endereço IP do cliente real e não o 192.168 (supondo que o endereço IP do balanceador de carga esteja sendo impresso)

Endereço do host mais detalhado: 192.168.255.9

Muitos agradecem se você puder ajudar.

Dave

ATUALIZAÇÃO:

Sem verniz na equação, tenho os seguintes LB - > NGINX e dentro do NGINX o seguintes existis

set_real_ip_from  192.168.255.0/24;
real_ip_header X-Forwarded-For;

Quando o NGINX registra o remote_addr, a primeira entrada abaixo imprime o endereço IP do cliente real

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
              '$status $body_bytes_sent "$http_referer" '
              '"$http_user_agent" "$http_x_forwarded_for"';


213.205.234.x - - [05/Sep/2012:09:42:08 -0700] "GET /2011/10/28/chicken-and-apples-in- honey-mustard-sauce/ HTTP/1.1" 200 18283 "-" "Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9100 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30" "213.205.234.x"

Com o verniz na equação LB - > Verniz - > NGINX

E dentro do NGINX eu mudei o set_real_ip_from para apontar para 127.0.0.1

set_real_ip_from  127.0.0.1;
real_ip_header X-Forwarded-For;

$ remote_addr no NGINX não imprime o endereço IP do cliente real:

192.168.255.9 - - [05/Sep/2012:09:46:41 -0700] "GET /2012/09/03/stuffed-baked-potatoes-deconstructed/ HTTP/1.1" 200 18159 "-" "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; ADR6400L Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" "69.255.125.x, 192.168.255.9"

Como você pode ver acima, o $ remote_addr que está sendo impresso é o endereço IP do Load Balancer: 192.168.255.9 em vez do remote_addr do cliente. Embora o "$ http_x_forwarded_for" 'esteja imprimindo o endereço correto, eu acho: "69.255.125.x, 192.168.255.9". Meu objetivo é fazer com que o $ remote_addr contenha o endereço IP correto

Obrigado Dave

ATUALIZAÇÃO:

Aqui está meu default.vcl de Varnish, comentou a parte mencionada por Shane, aqui está a saída atual do log de acesso do NGINX

127.0.0.1 - - [05/Sep/2012:11:16:43 -0700] "GET /wp-content/plugins/wp-pagenavi/pagenavi-css.css?ver=2.70 HTTP/1.1" 304 0 "http://mobilefoodblog.com/2011/10/28/chicken-and-apples-in-honey-mustard-sauce/" "Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; SCH-I405 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" "67.168.209.192, 192.168.255.9"


    # This is a basic VCL configuration file for varnish.  See the vcl(7)
    # man page for details on VCL syntax and semantics.
    # 
    # Default backend definition.  Set this to point to your content
    # server.
    # 

    backend default {
         .host = "localhost";
         .port = "8080";
    }

    sub detect_device {
      # Define the desktop device
      set req.http.X-Device = "desktop";

      if (req.http.User-Agent ~ "iP(hone|od)" || req.http.User-Agent ~ "Android" || req.http.User-Agent ~ "iPad") {
        # Define smartphones and tablets
        set req.http.X-Device = "smart";
      }

      elseif (req.http.User-Agent ~ "SymbianOS" || req.http.User-Agent ~ "^BlackBerry" || req.http.User-Agent ~ "^SonyEricsson" || req.http.User-Agent ~ "^Nokia" || req.http.User-Agent ~ "^SAMSUNG" || req.http.User-Agent ~ "^LG") {
        # Define every other mobile device
        set req.http.X-Device = "other";
      }
    }

    acl purge {
            "localhost";
    }

    sub vcl_recv {
       call detect_device;

         # if (req.restarts == 0) {
         #  if (req.http.x-forwarded-for) {
         #      set req.http.X-Forwarded-For =
         #          req.http.X-Forwarded-For ", " client.ip;
         #  } else {
         #      set req.http.X-Forwarded-For = client.ip;
         #  }
         # }

       if (req.request == "PURGE") {
            if (!client.ip ~ purge) {
                 error 405 "Not allowed.";
            }
            return(lookup);
       }

    if (req.url ~ "^/$") {
          unset req.http.cookie;
        }
    }

    sub vcl_hit {
            if (req.request == "PURGE") {
                    set obj.ttl = 0s;
                    error 200 "Purged.";
            }
    }

    sub vcl_miss {
        if (req.request == "PURGE") {
                    error 404 "Not in cache.";
        }

        if (!(req.url ~ "wp-(login|admin)")) {
                            unset req.http.cookie;
        }

        if (req.url ~ "^/[^?]+.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.|)$") {
               unset req.http.cookie;
               set req.url = regsub(req.url, "\?.$", "");
        }

        if (req.url ~ "^/$") {
               unset req.http.cookie;
        }
    }

    sub vcl_fetch {
            if (req.url ~ "^/$") {
               unset beresp.http.set-cookie;
            }

        if (!(req.url ~ "wp-(login|admin)")) {
               unset beresp.http.set-cookie;
        }
    }

    sub vcl_hash {
         set req.hash += req.url;
         if (req.http.host) {
             set req.hash += req.http.host;
         } else {
             set req.hash += server.ip;
         }

         # And then add the device to the hash (if its a mobile device)
         if (req.http.X-Device ~ "smart" || req.http.X-Device ~ "other") {
           set req.hash += req.http.X-Device; 
         }

         return (hash);
    }
    
por ddavtian 05.09.2012 / 01:02

3 respostas

4

Como o Varnish está em execução em cada servidor que está executando o nginx, a origem da conexão da perspectiva do nginx é 127.0.0.1, não o balanceador de carga mais.

set_real_ip_from 192.168.255.0/24;

Esse é o problema; O nginx não "confiará" no cabeçalho X-Forwarded-For quando a conexão se originar de 127.0.0.1 (o processo Varnish); tudo em que confia é toda a rede 192.168.255.0/24. Adicione uma autorização para confiar no cabeçalho quando o Varnish o enviar.

set_real_ip_from 127.0.0.1;

Editar:

O nginx se comporta mal ao analisar o cabeçalho X-Forwarded-For do IP do cliente "real"; procura a última entrada no cabeçalho, que nunca é o IP do cliente real quando há mais de uma entrada. Consulte esta pergunta para obter mais informações sobre isso problema.

Eu recomendaria que o Varnish parasse de adicionar seu próprio cabeçalho X-Forwarded-For . Você vai querer despir essa parte da função vcl_recv :

if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
        set req.http.X-Forwarded-For =
            req.http.X-Forwarded-For + ", " + client.ip;
    } else {
        set req.http.X-Forwarded-For = client.ip;
    }
}

Forneça sua configuração vcl atual, se precisar de ajuda, o que precisa mudar para você, pois isso pode ser explicitamente configurado ou anexado pelos padrões (ou ambos).

Editar 2:

Troque isso para a função vcl_recv em sua configuração do Varnish; Ele combina as personalizações que você configurou com o comportamento padrão ao remover a trapalha X-Forwarded-For presente por padrão.

sub vcl_recv {
    call detect_device;
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        return(lookup);
    }
    if (req.url ~ "^/$") {
        unset req.http.cookie;
    }
    # Default logic follows; it's normally appended.
    # It'll still be appended, but having the return(lookup)
    # prevents its use. X-Forward-For header behavior removed.
    if (req.request != "GET" &&
      req.request != "HEAD" &&
      req.request != "PUT" &&
      req.request != "POST" &&
      req.request != "TRACE" &&
      req.request != "OPTIONS" &&
      req.request != "DELETE") {
        /* Non-RFC2616 or CONNECT which is weird. */
        return (pipe);
    }
    if (req.request != "GET" && req.request != "HEAD") {
        /* We only deal with GET and HEAD by default */
        return (pass);
    }
    if (req.http.Authorization || req.http.Cookie) {
        /* Not cacheable by default */
        return (pass);
    }
    return (lookup);
}
    
por 05.09.2012 / 05:52
2

Parece que seu balanceador de carga não está passando o endereço IP do cliente em nenhum cabeçalho. Como você não disse o que estava usando para o balanceador de carga, é impossível fornecer uma solução específica, mas em geral você deseja configurar o balanceador de carga para colocar o endereço IP do cliente em um dos cabeçalhos (como X-Forwarded-For ). Você também pode designar um cabeçalho personalizado para isso, se quiser.

Se o seu balanceador de carga estiver configurando o X-Forwarded-For, configure seus servidores Varnish para definir um cabeçalho diferente de X-Forwarded-For, para que você tenha visibilidade total do endereço IP do cliente e de qual servidor manipulou o pedido.

    
por 05.09.2012 / 01:06
0

Supondo que seu balanceador de carga use o cabeçalho X-Forwarded-For para HTTP e HTTPS, então ...

... em verniz você deve ter isso

sub vcl_recv { 
...
  set req.http.X-Forwarded-For = req.http.X-Forwarded-For;

... em Nginx você deveria ter isto

server {
...
  set_real_ip_from 192.168.255.0/24;
  real_ip_header X-Forwarded-For;

Eu adicionarei que você deve estar realmente executando apenas 1 instância do Varnish, ele derrota o propósito de ter vários caches (já que o balanceador de carga pode passar um pedido para uma instância do Varnish não iniciada) . Suas taxas de acerto serão piores, sem mencionar que é apenas um desperdício de recursos.

    
por 05.09.2012 / 19:19

Tags