Un proxy inverse ou "reverse proxy" est une machine installée entre un client Web et un serveur Web et dont le rôle est de relayer les requêtes HTTP/HTTPS en provenance du client vers l'application Web. L'intérêt de cette disposition est d'apporter une couche de sécurisation supplémentaire notamment en filtrant les requêtes et en masquant l'architecture des sites Web desservis. Le reverse proxy peut également apporter une fonction de répartition de charge, cache Web ou encore d'authentification si l'application Web protégée n'en dispose pas.
Dans cet article, nous allons décrire comment installer un reverse proxy basique à l'aide d'Apache HTTPd sous Rocky Linux 9, puis nous créerons un virtualhost afin de relayer les requêtes vers un serveur interne Moodle.
Pré-requis
- Une machine avec Rocky Linux 9 à jour.
- Un serveur Web interne vers lequel on pourra relayer les requêtes HTTP
Installer Apache HTTPd
- Installer le service Apache :
# dnf install httpd mod_ssl
- Comme nous utilisons Apache HTTPd en mode Proxy, nous devons nous assurer que les modules suivants sont bien activés dans le fichier /etc/httpd/conf.modules.d/00-proxy.conf et le fichier /etc/httpd/conf.modules.d/00-ssl.conf :
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule ssl_module modules/mod_ssl.so - Autoriser dans Firewalld l'accès au serveur Apache HTTPd sur les ports 80 et 443 :
# firewall-cmd --permanent --add-service=http
# firewall-cmd --permanent --add-service=https
# firewall-cmd --reload - Par défaut, SELinux empêche Apache HTTPd d'initier des connexions. Nous devons donc ajuster SELinux avec la commande suivante afin que HTTPd puisse relayer des requêtes :
# /usr/sbin/setsebool -P httpd_can_network_connect 1
- Lancer Apache immédiatement et automatiquement au redémarrage :
# systemctl start httpd
# systemctl enable httpd - Constater qu'après le chargement du module SSL, la clé privée localhost.key et le certificat localhost.crt autosigné par défaut ont été créés :
# ll /etc/pki/tls/private/localhost.key
# ll /etc/pki/tls/certs/localhost.crt
Création d'un virtualhost SSL
Nous souhaitons ici créer un vitualhost SSL identifié par le nom plutôt que par l'adresse IP. Nous souhaitons également qu'un utilisateur faisant une requête vers le virtualhost en HTTP soit redirigé automatiquement vers le virtualhost en HTTPS. Nous devons donc créer en tout 2 virtualhosts avec une redirection du premier vers le deuxième. Les fichiers *.conf situés dans le répertoire /etc/httpd/conf.d étant intégrés automatiquement dans la configuration HTTPd, nous allons créer dans ce répertoire un fichier contenant les virtualhosts.
- Aller dans le répertoire /etc/httpd/conf.d :
# cd /etc/httpd/conf.d
- Créer le fichier moodle.externe.lan.conf avec le contenu suivant :
<VirtualHost *:80>
La directive SSLEngine active ou désactive le moteur SSL dans le virtualhost
ServerName moodle.externe.lan
Redirect permanent / https://moodle.externe.lan/
</VirtualHost>
<VirtualHost *:443>
ServerName moodle.externe.lan
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLProtocol all -TLSv1.1 -TLSv1 -SSLv2 -SSLv3
ProxyPass / http://lin-sv01.interne.lan/moodle/
ProxyPassReverse / http://lin-sv01.interne.lan/moodle/
</VirtualHost>
La directive SSLCertificateFile spécifie le certificat à envoyer au client pour le chiffrement RSA de cette connexion HTTPS
La directive SSCertificateKeyFile spécifie le fichier de clé privée utilisée par le serveur pour autosigner le certificat et pour le déchiffrement RSA
La directive SSLProtocol définit les versions de protocole de chiffrement TLS/SSL qui seront acceptées ou refusées avec ce virtualhost
La directive ProxyPass remplace http://moodle.externe.lan/ par http://lin-sv01.interne/moodle/ avant de relayer la requête vers le serveur interne lin-sv01.
La directive ProxyPassReverse n'est pas obligatoire mais est recommandée car elle permet notamment de gérer correctement les REDIRECT effectués par le serveur web interne. En effet, il faut bien comprendre dans notre exemple que le navigateur du client ne peut ni résoudre ni accéder au réseau privé "interne.lan" directement. Si l'application Web située sur le serveur interne lin-sv01 répond à une requête par un REDIRECT, elle va logiquement le faire en ajoutant dans le header HTTP de la réponse le champ LOCATION avec une URL interne par exemple : LOCATION : http://lin-sv01.interne.lan/new-moodle/. Si rien n'est modifié par le reverse proxy lors de la réponse au client, le navigateur va alors lancer la requête de redirection vers une adresse "interne" à laquelle il ne pourra jamais accéder... La directive ProxyPassReverse permet de résoudre ce problème car elle demande au reverse proxy de modifier le header lors de la réponse au client. En l'occurence, le champ LOCATION sera mis à jour avec le FQDN externe du reverse proxy, c'est-à-dire dans notre cas moodle.externe.lan. - Dans notre exemple, le reverse proxy répond à l'adresse moodle.externe.lan. Il faut donc que cette adresse soit résoluble par un DNS dans notre réseau de test. Comme le reverse proxy est susceptible de présenter plusieurs virtualhost sur la même adresse IP, il est plus cohérent d'ajouter dans le DNS des alias (CNAME) de l'adresse du revers proxy pour tous les "ServerName" de tous les VirtualHost accessibles. Notons que dans un cas plus proche de la réalité, le reverse proxy serait accessible publiquement sur le Web et son adresse devrait donc être résoluble via un DNS public.
- Relancer le service httpd :
# systemctl restart httpd
Tester l'accès au site Web
- Une fois le virtualhost en place, la résolution DNS ajoutée et les éventuelles règles de parefeu créées, nous pouvons effectuer un test d'accès à l'URL en HTTP (non SSL) déclarée dans notre virtualhost http://moodle.externe.lan
- Etant donné que le certificat utilisé pour la connexion HTTPS est autosigné, nous obtenons le message d'avertissement suivant. Dans le cas d'un serveur de production ouvert au public, nous aurions utilisé un certificat signé par une autorité de certification publique, ce qui n'aurait pas fait apparaître ce message. Dans notre cas, nous pouvons bien sûr cliquer sur "avancé" pour poursuivre vers le site web.
- Nous accédons maintenant à l'application en HTTPS, ce qui montre que la redirection HTTP vers HTTPS a bien fonctionné et que les requêtes sont bien relayées 😎.
Liens
https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/How-to-configure-Apache-as-a-reverse-proxy-example
https://www.netnea.com/cms/apache-tutorial-9_setting-up-a-reverse-proxy/