J'ai la configuration suivante:
(internet) ---> [ pfSense Box ] /-> [ Apache / PHP server ]
[running HAproxy] --+--> [ Apache / PHP server ]
+--> [ Apache / PHP server ]
\-> [ Apache / PHP server ]
Pour les requêtes HTTP, cela fonctionne très bien , les requêtes sont très bien distribuées sur mes serveurs Apache. Pour les demandes SSL, j'ai eu HAproxy distribuer les demandes en utilisant TCP équilibrage de charge, et cela a fonctionné cependant puisque HAproxy n'a pas agi comme un proxy, il n'a pas ajouté le X-Forwarded-For
En-tête HTTP et les serveurs Apache/PHP ne connaissaient pas la véritable adresse IP du client.
J'ai donc ajouté stunnel
devant HAproxy, lisant que stunnel pourrait ajouter le X-Forwarded-For
En-tête HTTP. Cependant, le paquet que j'ai pu installer dans pfSense n'ajoute pas cet en-tête ... aussi, cela tue apparemment ma capacité à utiliser les requêtes KeepAlive , que j'aimerais vraiment garder. Mais le plus gros problème qui a tué cette idée était que Stunnel convertissait les requêtes HTTPS en requêtes HTTP simples, donc PHP ne savait pas que SSL était activé et tentait de rediriger vers le site SSL.
Comment puis-je utiliser HAproxy pour équilibrer la charge sur un certain nombre de serveurs SSL, permettant à ces serveurs de connaître à la fois l'adresse IP du client et de savoir que SSL est utilisé ? Et si possible, comment le faire sur mon serveur pfSense?
Ou devrais-je laisser tomber tout cela et utiliser simplement nginx?
Vous n'avez pas besoin de tout laisser tomber, vous pouvez simplement utiliser nginx devant haproxy pour le support SSL, en gardant toute votre configuration d'équilibrage de charge. Vous n'avez même pas besoin d'utiliser nginx pour HTTP si vous ne le souhaitez pas. Nginx peut transmettre à la fois X-Forwarded-For et un en-tête personnalisé indiquant que SSL est utilisé (et les informations de certificat client si vous le souhaitez). Extrait de configuration Nginx qui envoie les informations requises:
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;
Pour mémoire, comme ce fil est souvent mentionné concernant HAProxy + SSL, HAProxy prend en charge SSL natif des deux côtés depuis 1.5-dev12. Ainsi, avoir X-Forwarded-For, HTTP keep-alive ainsi qu'un en-tête indiquant au serveur que la connexion a été établie via SSL est aussi simple que ce qui suit:
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 ...
...
Je suis sûr qu'au moment où vous avez trouvé quelque chose de différent, mais au moins les nouveaux visiteurs auront la solution facile maintenant :-)
Pour tous ceux qui trouvent cette question, j'ai suivi les conseils d'Ochoto et utilisé nginx. Voici les étapes spécifiques que j'ai utilisées pour que cela fonctionne sur mon routeur pfSense :
À l'aide de l'interface Web de pfsense, j'ai installé pfsense package PfJailctl et le package "jail_template" sous Système> Packages pour pouvoir créer une prison FreeBSD sous laquelle compiler et installer nginx sur le système pfsense.
J'ai configuré une prison pour mon serveur nginx sous Services> Prisons , donnant à la nouvelle prison le même nom d'hôte et la même adresse IP que l'alias IP virtuel que j'avais HAproxy en cours d'exécution. J'ai lié la prison à l'interface WAN. J'ai utilisé le modèle de prison par défaut et activé unionfs plutôt que nullfs.
Une fois la prison démarrée, je me suis connecté à la boîte pfsense et j'ai exécuté jls
pour trouver le numéro de la prison. J'ai ensuite couru jexec 1 sh
pour obtenir un Shell à l'intérieur de la prison. De là, j'ai configuré les ports BSD et installé nginx en utilisant:
portsnap extract
portsnap fetch update
cd /usr/ports/www/nginx
make install clean
J'ai ensuite configuré nginx pour écouter sur le port 443 et transmettre toutes les demandes à HAproxy sur le port 80, y compris la véritable IP et l'état SSL dans les en-têtes HTTP. Ma usr/local/etc/nginx/nginx.conf
ressemble à:
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;
}
}
}
J'ai ensuite modifié mon PHP application pour détecter le X-Forwarded-Proto
En-tête HTTP:
function usingSSL()
{
return (
(isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' )
|| (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' ));
}
La configuration finale est donc:
(internet) ---> [ -> nginx -> haproxy -]--> (pool of Apache servers)
[ (pfSense server) ]
Ma configuration pour une version 1.5-dev-17 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
Il utilise le ssl_fc
ACL. Veuillez noter que le option http-server-close
une partie est très importante.
HAProxy ne peut pas toucher un backend SSL sans utiliser le raw TCP, perdant X-Forwarded-For
, mais, vous pourriez potentiellement rechiffrer le trafic avec un stunnel d'écoute pour le transit backend. Moche, cependant.
J'aime mieux l'approche d'Ochoto, avec une mise en garde: nginx est un équilibreur de charge parfaitement capable; si vous l'utilisez, je dirais l'utiliser pour tout. Proxy votre HTTPS entrant pour charger des backends HTTPS équilibrés - et de cette façon, il n'y a pas besoin d'en-têtes personnalisés pour les informations SSL (sauf si vous avez besoin du certificat client).
J'ai implémenté une solution l'année dernière pour intégrer HAProxy à pfSense de manière à exploiter toutes les fonctionnalités de HAProxy et à maintenir une bonne isolation avec pfSense. Il s'agit donc d'une option viable pour les environnements de production . SSL est terminé sur HAProxy . J'ai installé HAProxy dans une prison dans pfSense en utilisant ezjail et Ports Collection . De cette façon, il est très facile de maintenir les deux composants indépendamment. Et vous pouvez installer la version que vous souhaitez. J'ai commencé avec 1.5-dev13. Et depuis, cela fonctionne parfaitement pour moi. J'ai documenté le tout ici.
Installation de HAProxy sur pfSense
BTW Willy, merci beaucoup pour cet excellent produit.