Haproxy peut être utilisé en mode http, avec prise en charge des acl(s), ou en mode tcp (pass-through). Mon article ne présente que le mode http.

Maquette

  • Le reverse-proxy dispose de l'adresse 192.168.16.30 dans mon exemple. J'utilise une Debian 10.
  • Le serveur web qui héberge www.foo.net : 192.168.16.101 (il n'y a pas de load-balancing)
  • Le serveur web qui héberge www.bar.net : 192.168.16.102 (il n'y a pas de load-balancing)
  • Le décalage de 2 espaces est obligatoire (ce n'est pas pour faire joli)
  • Des règles NAT sur 80 et 443 dirigent le trafic WAN vers le reverse-proxy (iptables ou pfsense)

Configuration rapide, en http

  • Fichier /etc/haproxy/haproxy.cfg
global
  log /dev/log    local0
  log /dev/log    local1 notice
  chroot /var/lib/haproxy
  stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
  stats timeout 30s
  user haproxy
  group haproxy
  daemon

  # Default SSL material locations
  ca-base /etc/ssl/certs
  crt-base /etc/ssl/private

  # Default ciphers to use on SSL-enabled listening sockets.
  # For more information, see ciphers(1SSL). This list is from:
  #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
  # An alternative list with additional directives can be obtained from
  #  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
  ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
  ssl-default-bind-options no-sslv3

defaults
  log global
  mode http
  option httplog
  option dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
  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
  mode http
  bind 192.168.16.30:80
  default_backend b1

backend b1
  server s101 192.168.16.101:80

Utilisation d'acl(s)

  • Dans la partie "frontend" il est possible de relier les backend(s) en fonction de règles acl(s) précises
  • Dans la partie "backend" il serait possible de gérer la haute disponibilité (je ne le fait pas dans mon article)
  • Les parties "global" et "defaults" restent identiques.
frontend http
  mode http
  bind 192.168.16.30:80
 
  acl foo hdr(host) -i www.foo.net
  use_backend b1 if foo

  acl bar hdr(host) -i www.bar.net
  use_backend b2 if bar

backend b1
  server s101 192.168.16.101:80

backend b2
  server s102 192.168.16.102:80

Https

  • Pour créer des certificats SSL auto-signés j'utilise le script suivant : lgmSsl
  • Il faut créer un nouveau dossier /etc/haproxy/ssl et déposer le(s) certificat(s) au format pem.
  • Haproxy retrouve automatiquement le certificat qui est lié à un site, le nom doit donc être correctement choisi. Dans notre cas : www.foo.net.pem
frontend http
  mode http
  bind 192.168.16.30:80

  acl foo hdr(host) -i www.foo.net
  use_backend b1 if foo

frontend https
  mode http
  bind 192.168.16.30:443 ssl crt /etc/haproxy/ssl/

  acl foo hdr(host) -i www.foo.net
  use_backend b1 if foo

backend b1
  server s101 192.168.16.101:80

Forward IP

  • Pour que le proxy transmette l'adresse IP de la machine qui est à l'origine d'une requête web, il faut paramétrer le revers-proxy et le serveur http 
  • Configuration sur Haproxy, on active "forwardfor" :
frontend http
  mode http
  bind 192.168.16.30:80
  option httplog
  option forwardfor except 127.0.0.1

  acl foo hdr(host) -i www.foo.net
  use_backend b1 if foo

backend b1
  server s101 192.168.16.101:80
  • Sur le serveur web avec apache 2.4,  créez un fichier /etc/apache2/conf-available/remoteip.conf :
RemoteIPHeader X-Forwarded-for
RemoteIPInternalProxy 192.168.16.30
  • Activez la nouvelle configuration : a2enmod remoteip , puis a2enconf remoteip
  • Dans /etc/apache2/apache2.conf, modifier la ligne LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined par :
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
  • Relancez apache2.