Haproxy
HAProxy est une application qui permet de faire du Load Balancing. Dans ce tuto nous allons l'utiliser pour faire du reverse proxy.
Voici un schéma simple :
8080 ------> Serveur Web | 80/443 80/443 | 80 Clients --------> BOX --------> Serveur HAProxy ---------> Serveur Web | | 443 ------> Serveur Web
Déroulement :
- Le client envoie une requête web sur mon IP Fixe.
- Sur la box, le port 80 et 443 est ouvert et celui-ci contact le serveur HAProxy.
- HAProxy traite la requête web et revoie la requête sur le serveur demandé.
- Le serveur Web, lui, exécute et revois la réponse.
Cela permet clairement, de contacter plusieurs serveurs web avec une seule IP Fixe.
Installation
Le paquet haproxy est disponible dans les dépôts Debian. Nous pouvons installer la dernière version de haproxy en activant le dépôt Backports de Debian.
$ apt install haproxy
Il faut ensuite activer HAProxy. Éditer le fichier /etc/default/haproxy et remplacer :
ENABLED=0
par :
ENABLED=1
Terminologie
Haproxy utilise des termes assez classiques dans sa configuration, mais que nous allons tout de même revoir ici afin de bien savoir de quoi l'on parle dans la suite.
- bind : attacher en Anglais, permet de dire sur quelle IP et quel port haproxy va écouter. Par exemple, 192.168.1.1 sur le port 80
- frontend : c'est un bloc de configuration qui permet de définir toutes les règles qui s'appliqueront (domaines écoutés, limitations, etc). Un frontend peut s'appliquer à un ou plusieurs bind.
- backend : c'est un autre bloc de configuration, que l'on place derrière un frontend. Si le frontend gère ce qui est publique (à "l"avant" du serveur), le backend gère "l'arrière". C'est là que vous définirez les serveurs web vers lesquels envoyer les requêtes.
- acl : une "access control list" permet de définir des conditions dans un bloc, par exemple "si le domaine contient site1, alors faire cela, si la requête est en https, alors faire ceci"
Configuration
Plusieurs types de configurations sont possibles (+/- optimisé). Je vous propose ma version, mais n'hésitez pas a parcourir la documentation de HAProxy (modifier la version de HAProxy dans l'URL si besion).
La configuration ce fait dans un seul fichier : /etc/haproxy/haproxy.cfg
Voila une configuration : (Les commentaire vous aiderons a mieux comprends)
global
daemon
maxconn 256
log 127.0.0.1 local5 debug
spread-checks 10
tune.ssl.default-dh-param 2048
defaults
option dontlognull
mode http
stats enable
default-server inter 30s fastinter 5s
log global
option httplog
timeout connect 5000
timeout client 50000
timeout server 50000
timeout tunnel 1h
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
############
# FRONTEND #
############
###HTTP###
frontend http
bind 0.0.0.0:80 #HAproxy écoute sur le port 80
mode http #Activation du mode HTTP
option httplog #Activation des logs
###ACL###
acl host_web1_via_http hdr_end(host) domaine1.local #Si le host termine par "domaine1.local" alors l'acl "host_web1_via_http" est vrai
###USE_BACKEND###
use_backend web1_via_http if host_web1_via_http #Si l'acl "host_web1_via_http" est vrai, le "backend web1_via_http" sera utilisé (en bas de la config)
###DEFAULT_BACKEND###
default_backend gotohttps #Si aucun acl est valide, utiliser le backend "gotohttps" (en bas de la config)
###HTTPS###
frontend https
#HAproxy écoute sur le port 443, vérifie les certificats, accepte/refuse des ciphers et refuse le protocole sslv3
bind :443 ssl crt /repertoir/ou/sont/situé/les/certificats ciphers AESGCM+AES128:AES128:AESGCM+AES256:AES256:RSA+RC4+SHA:!RSA+AES:!CAMELLIA:!aECDH:!3DES:!DSS:!PSK:!SRP:!aNULL no-sslv3
mode http #Activation du mode HTTP
option httplog #Activation des logs
###ACL###
acl host_web2_via_https hdr_reg(host) ^(www.|)sousdomain1.domain2.local$ #Si le host est valider par l’expression régulière (www.sousdomaine1.domain2.local ou sousdomaine1.domain2.local) alors l'acl "host_web2_via_https" est vrai
acl host_web3_via_https hdr(host) sousdomain2.domain2.local #Si le host est sousdomaine2.domain2.local alors l'acl "host_web3_via_https" est vrai
###USE_BACKEND###
use_backend web2_via_https if host_web2_via_https #Si l'acl "host_web2_via_https" est vrai, le "backend web2_via_https" sera utilisé (en bas de la config)
use_backend web3_via_https if host_web3_via_https #Si l'acl "host_web3_via_https" est vrai, le "backend web3_via_https" sera utilisé (en bas de la config)
###########
# BACKEND #
###########
backend web1_via_http
option forwardfor except 127.0.0.1 #Permet de transferer l'IP du visiteur au serveur
server web1 ADRESESIP:8080 check maxconn 32 #Si le backend "web_en_http" est appelé, la requête http est envoyé sur le serveur dont l'IP et sont port (8080 par exemple) est définit
backend gotohttps
redirect scheme https code 301 if !{ ssl_fc } #revoie sur le fontend https
backend web2_via_https
option forwardfor except 127.0.0.1 #Permet de transferer l'IP du visiteur au serveur
server web2 ADRESESIP:80 check maxconn 32 #Si le backend "web2_via_https" est appelé, la requête http est envoyé sur le serveur dont l'IP et sont port (80 par exemple) est définit
backend web3_via_https
option forwardfor except 127.0.0.1 #Permet de transferer l'IP du visiteur au serveur
server web2 ADRESESIP:443 check maxconn 32 ssl verify none #Si le backend "web3_via_https" est appelé, la requête http'''s''' est envoyé sur le serveur dont l'IP et sont port (443 par exemple, remarque le commande ssl verify none permet de ne pas vérifier le certificat du serveur appelé) est définit
Information supplémentaire
ACL
Voici les différentes commande pour les acl :
- hdr(host) SOUSDOMAIN.DOMAIN : si le host est "SOUSDOMAIN.DOMAIN"
- hdr_beg(host) SOUSDOMAIN : si le host commence par le sous-domaine "SOUSDOMAIN"
- hdr_end(host) DOMAIN : si le host fini par le domain "DOMAIN"
- hdr_reg(host) REGEXP : si le host est valider par la regexp "REGEXP"
Backend
Voici les différentes commande pour les serveurs contenu des les backend
- check : verifie que le serveur est dispo
- maxconn 32 : accept 32 connextion en même temps
- ssl verify none : ne verifie pas le certificat du serveur appelé
Certificats
La commande "crt /repertoir/ou/sont/situé/les/certificats" permet de définir le répertoire où est placé les certificats.
haproxy gère les certificats au format pem, que vous pouvez simplement créer de la façon suivante en mergeant le .crt et le .key :
$ cat sousdomain2.domain2.local.crt sousdomain2.domain2.local.key > sousdomain2.domain2.local.pem
Test
Pour tester la configuration, il suffi de redémarrer le service:
$ service haproxy restart
Si la commande ne vous revoie pas erreur, c'est que votre configuration est bien pris en compte.
En revanche, si elle retourne une erreur, exécuter la commande de vérification de la configuration :
$ haproxy -c -f /etc/haproxy/haproxy.cfg
Celui-ci vous retournera les lignes en erreur.
Accès par mot de passe
HAProxy permet de configurer un accès à un site par mot de passe à la manière des .htaccess d'Apache.
Création d'un groupe d'utilisateurs
userlist liste-utilisateurs
group utilisateurs-seedbox
group utilisateurs-toto
user seedman password $5$cDFwlRsuHkvtybY$xpEFL2ctNPEXXDijQNO.jrzPUsuRYRKHNQaS.n/qFB1 groups utilisateurs-seedbox
# user michal password $5$gZZsvtRWI$9JIU8pfHLG8BtYW5tceAKD1oNAjjfL5e4LwUfAW1sqA groups utilisateurs-seedbox
# user milosz password $1$R29iAdV/$1QUKx8eo6e5pcMIEgaZwt0 groups utilisateurs-toto
# user guest insecure-password guestpassword
Il est possible de préciser un mot de passe haché (DES, MD5, SHA-256 et SHA-512 pris en charge) via la directive password ou un mot de passe en clair via la directive insecure-password.
Les mots de passe hachés sont générables via la commande suivante :
printf "toto" | mkpasswd --stdin --method=sha-256
Utilisation d'un groupe d'utilisateurs
À utiliser à la suite d'une section backend :
acl connexion-auth http_auth_group(liste-utilisateurs) utilisateurs-seedbox
http-request auth realm "Authentification requise" unless connexion-auth
Notez la précision du groupe pouvant se connecté à la fin de l'ALC. On peut en mettre plusieurs en les séparent par des espaces. Si aucun groupe n'est précisé, Haproxy plante au démarrage.