haproxy + stunnel + keep-alive?

10

Me gustaría poner stunnel delante de haproxy 1.4 para manejar el tráfico HTTPS. También necesito stunnel para agregar el encabezado X-Fordered-For . Esto se puede lograr por los "stunnel-4.xx-xforwarded-for.diff" parches desde el sitio web haproxy.

Sin embargo, la descripción menciona:

Tenga en cuenta que este parche no funciona con keep-alive, ...

Mi pregunta es: ¿Qué significará esto en la práctica para mí? No estoy seguro

  1. si se trata de mantener vivo entre
    • cliente y stunnel
    • stunnel y haproxy
    • o servidor haproxy y backend?
  2. lo que esto significa para el rendimiento: si tengo 100 iconos en una página web, ¿el navegador tendrá que negociar 100 conexiones SSL completas, o puede reutilizar la conexión SSL, simplemente creando nuevas conexiones TCP?
Chris Lercher
fuente

Respuestas:

12

Se trata de HTTP keep-alive, que permite que múltiples solicitudes de recursos lleguen a través de una sola sesión TCP (y, con SSL, una sola sesión SSL). Esto es de gran importancia para el rendimiento de un sitio SSL, ya que sin mantener vivo, se necesitaría un protocolo de enlace SSL para cada recurso solicitado.

Entonces, la preocupación aquí es una gran sesión de mantenimiento desde el cliente hasta el servidor de fondo. Es una cosa importante para el rendimiento, y se toma como una rutina para los servidores HTTP modernos, pero este parche dice que no es compatible. Veamos por qué ...


Una sesión de mantenimiento es solo más solicitudes una tras otra: una vez que el servidor finaliza su respuesta a una solicitud, el servidor no envía un FINpaquete para finalizar la sesión TCP; el cliente simplemente puede enviar otro lote de encabezados.

Para comprender qué está haciendo ese parche, aquí hay un ejemplo de una conversación para mantener vivo:

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>

Aquí es donde se detendría una conexión que no se mantiene viva. Pero, keep-alive permite al cliente disparar a otro:

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

Para la identificación del cliente en el proxy, algunos proxy inversos pueden agregar el X-Forwarded-Forencabezado en cada solicitud del cliente. Eso le dice al servidor ascendente de dónde proviene la solicitud (en lugar de que cada solicitud se inicie desde la IP del proxy inverso), para la cordura en el registro y otras necesidades de aplicación.

El X-Forwarded-Forencabezado debe inyectarse en todas y cada una de las solicitudes de recursos del cliente enviadas a través de la conexión de mantenimiento, ya que los encabezados completos se envían cada vez; el manejo del X-Forwarded-Forencabezado y la traducción a él como la solicitud "real" IP se realiza por solicitud, no por sesión de TCP-keep-alive. Y oye, tal vez hay un increíble software de proxy inverso que usa una sola sesión de mantenimiento para atender solicitudes de múltiples clientes.

Aquí es donde falla este parche.


El parche en ese sitio observa el búfer de la sesión TCP para el final del primer conjunto de encabezados HTTP en la secuencia e inyecta el nuevo encabezado en la secuencia después del final de ese primer conjunto de encabezados. Una vez hecho esto, considera el X-Forwarded-Fortrabajo realizado y deja de buscar el final de nuevos conjuntos de encabezados. Este método no tiene conocimiento de todos los encabezados futuros que lleguen a través de solicitudes posteriores.

Realmente no puedo culparlos; Stunnel no fue realmente creado para manejar y traducir el contenido de sus transmisiones.

El efecto que esto tendría en su sistema es que la primera solicitud de una secuencia de mantenimiento mantendrá el X-Forwarded-Forencabezado inyectado correctamente, y todas las solicitudes posteriores funcionarán bien, pero no tendrán el encabezado.

A menos que exista otro parche de inyección de encabezado que pueda manejar múltiples solicitudes de clientes por conexión (u obtener este ajustado con la ayuda de nuestros amigos en Stack Overflow), es posible que deba buscar otras opciones para su terminación SSL.

Shane Madden
fuente
1
Excelente respuesta, gracias. Me recuerda por qué es una buena idea hacer preguntas aquí.
Chris Lercher
1
Para permitir tener una inyección de encabezado keep-alive en stunnel, necesitaría poder hablar casi todo HTTP, lo que sería una gran cantidad de trabajo. Dicho esto, también puede usar el protocolo PROXY de HAproxy (que requiere un parche para stunnel o alternativamente stud ) e inyectar el encabezado en HAproxy. Ver la documentación para obtener más información (de caché de Google, como el sitio HAProxy parece ser parcialmente hacia abajo ATM)
Holger Sólo
3

Similar a lo que publiqué en otro hilo, HAProxy admite SSL nativo en ambos lados desde 1.5-dev12. Entonces, tener X-Fordered-For, HTTP keep-alive y un encabezado que le dice al servidor que la conexión se realizó a través de SSL es tan simple como lo siguiente:

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 ...
    ...

Es mucho más fácil que parchear stunnel y mucho mejor que tener que dejar de mantener vivo.

Willy Tarreau
fuente
Es posible que desee utilizar ssl_fc en lugar de is_ssl
josch
2

Extendiendo la excelente respuesta de Shane, podría usar Nginx como terminador SSL frente a HAproxy. Maneja correctamente keep-alive entre el cliente y nginx, que es el lado más sensible a la latencia y hace una nueva conexión al back-end para cada solicitud del cliente, enviando el X-FORWARDED-FOR en cada uno.

Ochoto
fuente
1
Sin embargo, si necesita websockets, entonces nginx no funcionará.
w00t
Además, es compatible con la caché de sesión SSL.
3molo