Haproxy Apache2 X Forwarded For

Publié le 13 mars 2021

Haproxy en frontend et Apache2 en backend

Il y a peu j’ai fait l’acquisition d’un petit serveur à la maison. L’objectif était de remettre quelques services non critiques sur celui-ci.

Le setup est le suivant : j’ai un haproxy qui écoute sur les ports 80/TCP et 443/TCP. Les sites web sont sur une machin virtuelle où il y a un apache2 qui est configuré pour répondre aux différents sites web. J’ai décidé d’utiliser haproxy alors que j’aurais pu reprendre mes anciennes configurations à base de nginx. Pourquoi ? Afin d’approfondir et d’apprendre mieux haproxy que je trouve très chouette au passage.

On peut se représenter ainsi le flux : utilisateur -> haproxy (80/TCP) -> haproxy (443/TCP) -> VM Linux avec Apache2.

Du coup je me suis donc lancé dans la configuration de haproxy. J’ai plusieurs sites web qui sont hébergés sur la même VM donc j’ai tenté de voir s’il était possible de factoriser la configuration de haproxy, la réponse est oui. D’ailleurs ma configuration n’est pas encore optimale mais faut ce que je veux pour le moment.

Ainsi, dans le répertoire /etc/haproxy j’ai créé le fichier websites.map qui permet de faire de la correspondance entre un vhost et un backend haproxy.

Concrètement cela ressemble à :

root@betelgeuse:/etc/haproxy# cat websites.map 
hindy.lovetux.net       bk_hindy
matrix.lovetux.net      bk_matrix
root@betelgeuse:/etc/haproxy#

Puis la configuration que j’ai mis en place dans /etc/haproxy/haproxy.cfg est la suivante :

frontend websites
        bind *:80
        bind :443 ssl crt /etc/haproxy/ssl/lovetux.net.pem
        http-request redirect scheme https unless { ssl_fc }
        mode http
        option forwardfor
        http-request set-header X-Forwarded-Proto https if { ssl_fc }
        http-request set-header X-Forwarded-Proto http if !{ ssl_fc }

        use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/websites.map,bk_default)]

backend bk_hindy
        mode http
        server web-soli 192.168.69.1:80

backend bk_matrix
        mode http
        server web-soli 192.168.69.1:8008

On notera plusieures choses importantes dans cette configuration :

  • l’utilisation de l’option http-request qui permet de forcer la redirection HTTP vers HTTPS ;
  • le fait que l’on souhaite indiquer l’utilisation de l’entête forwardfor ;
  • l’utilisation de notre fichier map (/etc/haproxy/websites.map).

Côté Apache la configuration est plutôt aisée, ainsi voici un fichier de configuration de vhost :

<VirtualHost 192.168.69.1:80>
        ServerName hindy.lovetux.net
        DocumentRoot /srv/sites/hindy/hindy.lovetux.net
        <Directory /srv/sites/hindy/hindy.lovetux.net>
                Require all granted
                AllowOverride all
                Options -Indexes
        </Directory>
        ErrorLog /var/log/apache2/hindy.lovetux.net.error.log
        CustomLog /var/log/apache2/hindy.lovetux.net.access.log combined
</VirtualHost>

Du très très classique.

Puis ensuite j’ai commencé à regarder les logs côté Apache et j’avais complètement oublié que l’adresse IP qui serait remontée serait celle locale et non l’adresse IP du client source. Etant donné que haproxy est correctement configuré et qu’il comporte la direction option forwardfor, il convient donc de regarder la configuration côté Apache.

Sur ma Debian 10 j’ai ainsi modifié le fichier /etc/apache2/apache2.conf.

Initialement il y a cette ligne :

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

Nous remplaçons cette ligne par :

LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

On constate que c’est presque la même ligne mais au caractère %a qui est utilisé. Ainsi, maintenant nos logs apache contiennent l’adresse IP cliente.