18 votos

¿Cómo puedo utilizar HAproxy con SSL y obtener X-Forwarded-For encabezados Y decirle a PHP que SSL está en uso?

Tengo la siguiente configuración:

(internet) ---> [  pfSense Box  ]    /-> [ Apache / PHP server ]
                [running HAproxy] --+--> [ Apache / PHP server ]
                                    +--> [ Apache / PHP server ]
                                     \-> [ Apache / PHP server ]

Para las solicitudes HTTP que esto funciona genial, las solicitudes se distribuyen a mis servidores Apache bien. Las solicitudes SSL, tuve HAproxy la distribución de las solicitudes mediante el uso de TCP equilibrio de carga, y funcionó sin embargo, desde HAproxy no actuar como un proxy, no añadir el X-Forwarded-For encabezado HTTP, y el Apache / PHP servidores no sabía el cliente la dirección IP real.

Así que, he añadido stunnel frente a HAproxy, la lectura que stunnel podría añadir el X-Forwarded-For encabezado HTTP. Sin embargo, el paquete que se podía instalar en pfSense no agregar este encabezado... también, al parecer, esto mata a mi capacidad para utilizar KeepAlive solicitudes, lo que realmente me gustaría mantener. Pero el problema más grande que mató a que la idea era que stunnel convierte las peticiones HTTPS en la llanura de solicitudes HTTP, por lo que PHP no sabía que SSL fue habilitado y trató de redirigir al sitio SSL.

¿Cómo puedo utilizar HAproxy para equilibrar la carga a través de un número de servidores SSL, que permite que los servidores a los dos sabemos que la dirección IP del cliente y saber que SSL está en uso? Y si es posible, ¿cómo puedo hacerlo en mi servidor pfSense?

O debo dejar todo esto y simplemente usar nginx?

29voto

Willy Tarreau Puntos2913

Sólo para el registro, como este hilo se refiere a menudo sobre HAProxy + SSL, HAProxy tiene soporte nativo SSL en ambos lados desde 1.5-dev12. Así que tener X-Forwarded-For, HTTP keep-alive así como un encabezado de decirle al servidor que la conexión se realizó a través de SSL es tan simple como el siguiente :

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

Estoy seguro de que por el tiempo que usted vino para arriba con algo diferente, pero al menos los nuevos visitantes obtendrá la solución más fácil ahora :-)

16voto

Ochoto Puntos988

Usted no tiene que soltarlo todo, sólo podría utilizar nginx en frente de haproxy para el soporte SSL, manteniendo todo su equilibrio de carga de configuración. Usted incluso no necesita usar nginx para HTTP, si usted no lo desea. Nginx pueden pasar X-Forwarded-For y un encabezado personalizado indicando SSL está en uso (y el cliente cert información si lo desea). Nginx config fragmento de código que envía la información requerida:

proxy_set_header SCHEME $scheme;      # http/https
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header CLIENT_CERT $ssl_client_raw_cert;

11voto

Josh Puntos4445

Para cualquier otra persona que se encuentra esta pregunta, he seguido Ochoto del consejo y utilizar nginx. He aquí los pasos específicos que he utilizado para hacer este trabajo en mi pfSense router:

  1. Utilizando el pfsense de la interfaz web, he instalado el pfsense PfJailctl paquete y el "jail_template" paquete bajo el Sistema de > Paquetes para que yo pudiera crear un FreeBSD cárcel en virtud de la cual para compilar e instalar nginx en el pfsense sistema.

  2. He configurado una cárcel para mi servidor nginx bajo Servicios > Cárceles, dando a la nueva cárcel el mismo nombre de host y la dirección IP de la dirección IP virtual alias que me había HAproxy ejecutando. Que unido a la cárcel a la interfaz WAN. He utilizado el valor predeterminado de la cárcel de la plantilla y habilitado unionfs en lugar de nullfs.

  3. Una vez que la cárcel se había iniciado, me SSHed en el pfsense caja y corrió jls encontrar la cárcel del número. Yo luego corrió jexec 1 sh para obtener una shell en el interior de la cárcel. A partir de ahí me configurar BSD puertos e instalado nginx el uso de:

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. Me configurar nginx para que escuche en el puerto 443, y aprobar todas las solicitudes para HAproxy en el puerto 80, incluyendo la IP real y el SSL condición dentro de los encabezados HTTP. Mi usr/local/etc/nginx/nginx.conf parece:

    worker_processes  1;
    
    events {
        worker_connections  2048;
    }
    
    http {
        upstream haproxy {
            server 209.59.186.35:80;
        }
    
        server {
            listen       443;
            server_name  my.host.name default_server;
            ssl                  on;
            ssl_certificate      my.crt;
            ssl_certificate_key  my.key;
            ssl_session_timeout  5m;
    
            ssl_protocols  SSLv3 TLSv1;
            ssl_ciphers  HIGH:!aNULL:!MD5;
            ssl_prefer_server_ciphers   on;
    
            location / {
                proxy_pass http://haproxy;
    
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
                proxy_set_header X-Forwarded-Proto https;
            }
        }
    
    }
    
  5. Luego he modificado mi aplicación PHP para detectar la X-Forwarded-Proto HTTP Encabezado:

    function usingSSL()
    {
        return (
           (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' )
            || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
                   && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' ));
    }
    

Así que el final de la instalación es:

(internet) ---> [ -> nginx -> haproxy -]--> (pool of apache servers)
                [    (pfSense server)  ]

4voto

Shane Madden Puntos81409

HAProxy no puede golpear un SSL backend sin usar raw TCP modo, perdiendo X-Forwarded-For, pero, usted podría volver a cifrar el tráfico con una escucha stunnel para el backend de tránsito. Feo, aunque.

Me gusta Ochoto del enfoque mejor, con una salvedad: nginx es perfectamente capaz de equilibrador de carga; si la vas a usar, yo diría que lo uso para todo. Proxy entrantes HTTPS para equilibrio de carga HTTPS motores - y de esa manera, no hay necesidad de encabezados personalizados para SSL información (a menos que usted no necesita el certificado de cliente).

4voto

greg0ire Puntos131

Mi configuración para un 1.5-dev-17 versión de haproxy:

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        #log loghost    local0 info
        maxconn 4096
        #chroot /usr/share/haproxy
        user haproxy
        group haproxy
        daemon
        #debug
        #quiet

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        option  http-server-close
        retries 3
        option redispatch
        fullconn 1000        
        maxconn 1000
        timeout queue 600s
        timeout connect 5s
        timeout client 600s
        timeout server 600s

frontend http-in
        bind *:80
        bind *:443 ssl crt /usr/local/etc/ssl/certs
        reqadd X-Forwarded-Proto:\ https if { ssl_fc }
        default_backend varnish-ha
        option forwardfor
backend varnish-ha
  server hafront1 10.1.69.1:6081  minconn 100 maxqueue 10000

Utiliza el ssl_fc ACL. Por favor, tenga en cuenta que el option http-server-close parte es muy importante.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: