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 lgmHaSsl
- 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.