Configuration Apache et reverse proxy

apache 5 déc. 2023

Nous avions vu dans un précédent article comment configurer un serveur LAMP, avec Apache en tant que serveur web.

La configuration initiale d'Apache indique le dossier /var/www/html/ comme dossier initial pour les sites hébergés.

Lorsque vous commencez à avoir plusieurs sites ou services sur votre serveur, notamment des sous-domaines, il est nécessaire d'adapter la configuration d'Apache.

Sur les distributions basées sur RHEL, comme Alma Linux que j'utilise, les fichiers de configuration d'Apache sont stockés dans le dossier /etc/httpd/ .

Pour la configuration des différents domaines et sous-domaines, nous allons utiliser le dossier /etc/httpd/conf.d/ qu'Apache scanne également.

Ces fichiers, finissant par l'extension .conf, indiquent entre autres à quel dossier ou quel service est relié tel domaine ou sous-domaine.

Prenons un exemple simple :

<VirtualHost *:80>
    ServerName www.domaine.fr
    ServerAlias domaine.fr
    Redirect 301 "/" "https://www.domaine.fr/"
</VirtualHost>

<VirtualHost *:443>

    ServerName www.domaine.fr
    ServerAlias domaine.fr

    DocumentRoot "/var/www/html"
    ServerAdmin [email protected]

    Options -Indexes +FollowSymLinks -ExecCGI -MultiViews

    SSLEngine On
    SSLCompression Off

    SSLCertificateFile /root/.acme.sh/domaine.fr_ecc/domaine.fr.cer
    SSLCertificateKeyFile /root/.acme.sh/domaine.fr_ecc/domaine.fr.key
    SSLCertificateChainFile /root/.acme.sh/domaine.fr_ecc/ca.cer

    Protocols h2 http/1.1
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

    BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

    ErrorLog logs/www.domaine.fr_ssl_error_log
    TransferLog logs/www.domaine.fr_ssl_access_log
    LogLevel warn

    CustomLog logs/www.domaine.fr_ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>

Un fichier de configuration est constitué de "blocs" appelés VirtualHost.

Il s'agit d'un ensemble d'instructions indiquant la configuration correspondante à tel domaine ou sous-domaine en fonction du port.

Détaillons ces VirtualHost :
- <VirtualHost *:80> ... </VirtualHost> : indique les instructions pour une connexion via le port 80, donc http
- <VirtualHost *:443> ... </VirtualHost> : indique les instructions pour une connexion via le port 443, donc https

Pour le VirtualHost correspondant au port 80 :
- ServerName : le domaine ou sous-domaine concerné par ces paramètres
- ServerAlias : une alternative de domaine ou sous-domaine pour lequel les mêmes paramètres seront appliqués
- Redirect 301 : indique qu'une redirection permanente doit être faite

Pour le VirtualHost correspondant au port 443 :
- DocumentRoot : le chemin absolu auquel sera connecté le domaine ou le sous-domaine
- ServerAdmin : généralement l'adresse mail de l'administrateur du serveur, qui apparaît notamment en bas des pages "Internal Server Error"
- Options : paramètres indiquant le comportement d'Apache lors de l'affichage de tel dossier, par exemple "Options -Indexes" qui indique que le listing du contenu du dossier n'est pas autorisé (le "-" signifiant non autorisé et le "+" l'inverse)
- SSLEngine On : permet d'activer le moteur SSL d'Apache
- SSLCompression Off : permet de désactiver la compression au niveau SSL (conseillé car à l'origine de problèmes de sécurité)
- SSLCertificateFile/SSLCertificateKeyFile/SSLCertificateChainFile : préciser à Apache l'emplacement des différents fichiers liés au certificat SSL, dans l'ordre le certificat en lui-même, la clé privée et le certificat intermédiaire
- Protocols h2 http/1.1 : activer le protocole HTTP/2
- Header always set : permet d'indiquer un entête pour la connexion, ici pour activer le HSTS
- BrowserMatch : pour effectuer une action en fonction du navigateur, ici pour couper la connexion via Internet Explorer (car complètement obsolète)
- ErrorLog/TransferLog/LogLevel/CustomLog : pour configurer l'endroit où Apache va stocker ses logs

Une fois la configuration enregistrée, par exemple dans un fichier /etc/httpd/conf.d/vhost-www.domaine.fr.conf, il suffit de recharger Apache pour que cette nouvelle configuration soit prise en compte :

systemctl reload httpd

Ceci est une configuration simple dans le cas où vous voudriez connecter un domaine ou un sous-domaine à un dossier.

Passons maintenant au cas du reverse proxy, donc quand Apache fait le lien entre un domaine ou sous-domaine et un service tournant sur un port en particulier.

En reprenant le même fichier de configuration, il vous faut supprimer les lignes suivantes :
- DocumentRoot
- Options

Dans certains cas, notamment lors de l'utilisation de conteneurs Docker, les lignes suivantes peuvent causer des problèmes.
Elles seront donc à supprimer si c'est le cas :
- Protocols h2 http/1.1
- Header always set

Une fois ces lignes supprimées, vous devez rajouter les suivantes afin de faire le lien avec le bon port, celui où tourne l'application :

ProxyPreserveHost On
ProxyPass / http://127.0.0.1:7331/
ProxyPassReverse / http://127.0.0.1:7331/

En restant sur un exemple de conteneur Docker, l'explication des lignes est :
- ProxyPreserveHost : permet de transmettre le domaine ou sous-domaine utilisé au conteneur
- ProxyPass et ProxyPassReverse : les instructions concernant l'action du reverse proxy, à savoir l'IP et le port où sera transmise la connexion

Les lignes suivantes, celles commençant par RequestHeader, permettent dans l'ordre de :
- transmettre le protocole (généralement HTTP)
- transmettre au conteneur/application/services l'IP ayant demandé la connexion
- transmettre le statut SSL de la connexion (donc une URL en https)

RemoteIPHeader X-Forwarded-For
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RequestHeader set "X-Real-IP" expr=%{REMOTE_ADDR}
RequestHeader set "X-Forwarded-SSL" expr=%{HTTPS}

Il existe des cas plus complexes, par exemple quand le conteneur contient une application ayant besoin de websockets, ici sur le port 3000 :

<Location />
	Require all granted
</Location>

RewriteEngine On
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://127.0.0.1:3000/$1 [P,L]

ProxyPassReverse / http://127.0.0.1:3000/

Les possibilités pour faire du reverse proxy sont immenses mais une fois les bases saisies vous pourrez faire à peu près tout ce dont vous aurez besoin.

Il existe des outils permettant de gérer de façon plus simple et automatisée le reverse proxy, comme Nginx Proxy Manager, mais il est à mon sens important d'avoir compris le principe avant de les utiliser.

Mots clés

Samuel

Passionné par le web et les serveurs, je vous fais découvrir toutes sortes de news, de tutos, de scripts et autres points relatifs à cet univers sans limite !