haproxy + stunnel + keep-alive?

10

Eu gostaria de colocar stunnel na frente do haproxy 1.4 para lidar com o tráfego HTTPS. Também preciso de stunnel para adicionar o cabeçalho X-Forwarded-For . Isso pode ser alcançado pelos patches "stunnel-4.xx-xforwarded-for.diff" do site haproxy.

No entanto, a descrição menciona:

Observe que este patch não funciona com o keep-alive, ...

Minha pergunta é: O que isso significa na prática para mim? Não tenho certeza,

  1. se isso é sobre o manter vivo entre
    • cliente e stunnel
    • stunnel e haproxy
    • ou servidor haproxy e back-end?
  2. o que isso significa para o desempenho: se eu tiver 100 ícones em uma página da web, o navegador precisará negociar 100 conexões SSL completas ou poderá reutilizar a conexão SSL, apenas criando novas conexões TCP?
Chris Lercher
fonte

Respostas:

12

Trata-se do HTTP keep-alive, que permite que várias solicitações de recursos passem por uma única sessão TCP (e, com SSL, uma única sessão SSL). Isso é de grande importância para o desempenho de um site SSL, pois sem o keep-alive, um handshake SSL seria necessário para cada recurso solicitado.

Portanto, a preocupação aqui é uma grande sessão de manutenção do cliente até o servidor back-end. É importante para o desempenho e, como é óbvio, nos servidores HTTP modernos, mas esse patch diz que não é compatível. Vamos analisar o porquê ..


Uma sessão keep-alive é apenas mais solicitações uma após a outra - depois que o servidor termina sua resposta a uma solicitação, o servidor não envia um FINpacote para finalizar a sessão TCP; o cliente pode simplesmente enviar outro lote de cabeçalhos.

Para entender o que esse patch está fazendo, aqui está um exemplo de uma conversa mantida:

Cliente:

GET / HTTP/1.1
Connection: keep-alive
Host: domain.com
...

Servidor:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Apache
Content-Length: 34
.... (other headers)
<html><head>content!</head></html>

É aqui que uma conexão que não é mantida viva para. Porém, keep-alive permite ao cliente disparar outro:

GET /images/some/image.on.the.page.jpg HTTP/1.1
Connection: keep-alive
Host: domain.com
...

Para o ID do cliente no proxy, alguns proxies reversos podem ser adicionados ao X-Forwarded-Forcabeçalho em cada solicitação do cliente. Isso informa ao servidor upstream de onde a solicitação vem (em vez de todas as solicitações iniciadas pelo IP do proxy reverso), para sanidade no registro e em outras necessidades de aplicativos.

O X-Forwarded-Forcabeçalho precisa ser injetado em cada solicitação de recurso do cliente enviada através da conexão keep-alive, pois os cabeçalhos completos são enviados a cada vez; o manuseio do X-Forwarded-Forcabeçalho e a tradução para o IP de solicitação "real" são feitos por solicitação, não por TCP-keep-keep-session. E ei, talvez exista algum software de proxy reverso incrível por aí que use uma única sessão de manutenção para atender solicitações de vários clientes.

É aqui que esse patch falha.


O patch nesse site observa o buffer da sessão TCP para o final do primeiro conjunto de cabeçalhos HTTP no fluxo e injeta o novo cabeçalho no fluxo após o final do primeiro conjunto de cabeçalhos. Depois disso, ele considera o X-Forwarded-Fortrabalho concluído e para a verificação do final de novos conjuntos de cabeçalhos. Esse método não tem conhecimento de todos os cabeçalhos futuros que chegam por meio de solicitações subsequentes.

Não posso realmente culpá-los; o stunnel não foi realmente construído para manipular e traduzir o conteúdo de seus fluxos.

O efeito que isso teria no sistema é que a primeira solicitação de um fluxo keep-alive obterá o X-Forwarded-Forcabeçalho injetado corretamente e todas as solicitações subseqüentes funcionarão perfeitamente - mas elas não terão o cabeçalho.

A menos que exista outro patch de injeção de cabeçalho por aí que possa lidar com várias solicitações de clientes por conexão (ou que seja modificado com a ajuda de nossos amigos no Stack Overflow), talvez seja necessário procurar outras opções para o encerramento do SSL.

Shane Madden
fonte
1
Excelente resposta, obrigado. Me lembra, por que é uma boa idéia fazer perguntas aqui.
precisa saber é o seguinte
1
Para permitir a injeção de cabeçalho keep-alive no stunnel, seria necessário falar quase todo o HTTP, o que seria uma enorme quantidade de trabalho. Dito isto, você também pode usar o protocolo PROXY do HAproxy (que requer um patch para stunnel ou, alternativamente, pregos ) e injetar o cabeçalho no HAproxy. Consulte os documentos para obter mais informações (no cache do google, como o site do HAproxy parece estar parcialmente fora do caixa eletrônico) #
21651 Holger Apenas
3

Semelhante ao que eu publiquei em outro segmento, o HAProxy suporta SSL nativo em ambos os lados desde o 1.5-dev12. Portanto, manter o X-Forwarded-For, HTTP keep-alive e um cabeçalho informando ao servidor que a conexão foi feita através de SSL é tão simples quanto o seguinte:

listen front
    bind :80
    bind :443 ssl crt /etc/haproxy/haproxy.pem
    mode http
    option http-server-close
    option forwardfor
    reqadd X-Forwarded-Proto:\ https if { is_ssl }
    server srv1 1.1.1.1:80 check ...
    ...

É muito mais fácil do que consertar o stunnel e muito melhor do que ter que deixar o keep-alive.

Willy Tarreau
fonte
Você pode querer usar ssl_fc vez de is_ssl
Josch
2

Estendendo a excelente resposta de Shane, você pode usar o Nginx como terminador SSL na frente do HAproxy. Ele manipula corretamente o keep-alive entre o cliente e o nginx, que é o lado mais sensível à latência e faz uma nova conexão para back-end para cada solicitação do cliente, enviando o X-FORWARDED-FOR em cada um.

Ochoto
fonte
1
No entanto, se você precisar de websockets, o nginx não funcionará.
W00t
Além disso, ele suporta cache de sessão ssl.
3molo