Mise en place haproxy Debian 8

 

haproxy est ce qu'on appelle un load-balancer, ie un service permettant de dispatcher les requêtes TCP/HTTP vers plusieurs serveurs, appelés les backends. Mais haproxy peut aussi servir comme premier rempart contre les attaques sur les sites et applications Web.

Il est principalement utilisé en tant que load-balancer http vers des backends Apache/NginX/... mais peut aussi être utilisé pour faire du load-balancing vers d'autres services (mysql,redis,node.js ...).

Architecture

Pour ma maquette j'ai 5 vms sur mon serveur Proxmox :

  1. un proxy en frontal avec une ip publique et une ip privée
  2. deux serveurs web sur le réseau privé Apache + PHP 5.6
  3. 1 serveur SQL sur le réseau privé
  4. 1 serveur NFS sur le réseau privé

Un petit schéma pour illustrer tout cela. archi haproxyCette architecture est très perfectible, elle présente plusieurs SPOF :

  • le proxy (on peut penser mettre en place un cluster actif/passif pacemaker)
  • le serveur sql (réplication du serveur sql et cluster actif/passif ou load-balancing haproxy)
  • le stockage nfs (stockage réseau répliqué CEPH, GluterFS ...)

 

Installation

A partir de maintenant toutes mes installations se feront sur la nouvelle version majeure de Debian, ie Debian Jessie (version 8). Cependant pour bénéficier de la dernière version de haproxy, il faut mettre en place les backports jessie :

# echo "deb http://httpredir.debian.org/debian jessie-backports main contrib non-free" > /etc/apt/sources.list.d/backports.list
# apt-get update

On peut alors installer haproxy :

# apt-get install -t jessie-backports haproxy

 

Configuration

Le fichier de configuration est le suivant /etc/haproxy/haproxy.cfg. Faites un backup du fichier de base et voici ma conf, on en reparle après :

global
        log 127.0.0.1 local0
        log 127.0.0.1 local1 notice
        user haproxy
        group haproxy

defaults
        log global
        mode http
        option httplog
        option dontlognull
        retries 3
        option redispatch
        maxconn 2000
        timeout connect 5s
        timeout client 30s
        timeout server 10s
        timeout http-request 5s
        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


listen webstats IPSRV:8080
        stats enable
        stats hide-version
        stats scope webfarm
        stats scope webservers
        stats uri /
        stats realm Haproxy\ Statistics
        stats auth haproxy:secret
        stats refresh 10s

listen webfarm IPSRV:80
        default_backend webservers

backend webservers
        mode http
        balance roundrobin
        cookie LBN insert indirect nocache
        option httpclose
        option forwardfor
        server web01 192.168.14.41:80 weight 55 cookie web01 check inter 1s
        server web02 192.168.14.42:80 weight 45 cookie web02 check inter 1s

On redémarre haproxy pour vérifier que tout fonctionne :

# service haproxy restart
# # netstat -tpnl |grep haproxy
tcp        0      0 IPSRV:80        0.0.0.0:*               LISTEN      5845/haproxy    
tcp        0      0 IPSRV:8080      0.0.0.0:*               LISTEN      5845/haproxy

NB : remplacer IPSRV par l'ip publique du serveur.

 

Explications

global

Paramètres globaux de haproxy, les logs (dans syslog), l'utilisateur et le group de fonctionnement du service.

Il est possible aussi si le serveur héberge plusieurs services de chrooter haproxy.

 

defaults

Un certains nombre de paramètres importants dont :

  • mode : mode de fonctionnement par défaut du load-balancer : http donc load-balancing sur le niveau 7 du modèle OSI ;
  • maxconn : nombre de connexion maximum acceptée sur le frontal, cette option permet de limiter les connexions vers les backend et donc les attaques de type (D)DOS, si le nombre de connexion dépasse cette limite les nouvelles connexions seront refusées ;
  • timeout : différents timeout permettant de couper les connexions trop longues, ce qui permet par exemple de limiter les attaques de type slowloris ;
  • errorfile : il est possible de définir des pages d'erreur générique

 

stats

haproxy met à disposition une page de stats accessible, ici par exemple cette page sera accessible sur l'ip publique et le port 8080 avec une authentification assez complexe !!!

Visuellement cela nous donne ceci :

haproxy stats

frontend / backends

Les deux dernières parties concernent la configuration du frontend et backend pour l'accès aux services

Côté frontend, on écoute sur l'IP publique et le port 80 et on fait référence au backend "webservers" :

listen webfarm IPSRV:80
        default_backend webservers

Côté backend on défini les paramètres d'accès aux serveurs web :

backend webservers
        mode http
        balance roundrobin
        cookie LBN insert indirect nocache
        option httpclose
        option forwardfor
        server web01 192.168.14.41:80 weight 55 cookie web01 check inter 1s
        server web02 192.168.14.42:80 weight 45 cookie web02 check inter 1s

Définition du backend "webservers" qui fonctionne en mode http (vu plus haut)

Il existe plusieurs façon de répartir les requêtes :

  • roudnrobin : les requêtes sont réparties les unes après les autres sur chaque serveur de façon uniforme (modulo le paramètre weight) ;
  • leastconn : les requêtes sont envoyées vers le serveur le moins chargé ;
  • source : les requêtes seront toujours envoyées vers le même serveur backend pour la même source. Ce qui permet par exemple d'être sur de renvoyer vers le bon serveur web si les sessions sont stockées en dur

Les deux lignes "server ..." permettent de définir les paramètres de chaque serveur :

  • nom IP:port : le nom du serveur, son IP et son port ;
  • weight : on est en mode roundrobin mais on peut affecter un poids aux serveurs, par exemple si un est plus puissant que l'autre il aura un poids supérieur, la somme des poids doit faire 100 ;
  • cookie nom : nom du cookie, ce paramètre est en relation avec la ligne cookie. Cela permet de faire plus ou moins la même chose que pour le mode source. Le proxy va positionner un cookie ici nommé LBN avec pour contenu le nom du serveur backend ;
  • check inter 1s : vérifie toutes les secondes que le serveur est disponible

 

Basique mais utile

Cette configuration reste basique mais permet déjà d'assurer une fonction de répartition de charge vers les serveurs web, ainsi qu'un premier rempart de sécurité, outre les timeout et le nombre limite de connexion haproxy rejette toutes requêtes http mal formée.

Une petite lecture complémentaire :