Comme je vous l’ai expliqué à la fin du dernier chapitre, dans un environnement de production, Tomcat a besoin d’un serveur web qui gère les requêtes des clients, et qui ne lui transmette que les requêtes que doit traiter l’application Java. On parle de reverse-proxy pour désigner une application placée en frontal (directement en contact avec les clients) et qui joue le rôle d’un intermédiaire avec des applications placées en backend (sans contact direct avec les clients).
![Schéma de fonctionnement d'un reverse-proxy](https://user.oc-static.com/upload/2021/11/30/16382909620871_p3c2-1.png)
Les deux raisons principales qui peuvent amener à utiliser un reverse-proxy sont l’amélioration :
de la sécurité ;
des performances.
Nginx est un serveur web léger et performant. Il est particulièrement performant pour servir des fichiers statiques et pour analyser des URL. Pour cette raison, il est couramment employé en tant que reverse-proxy. Le backend peut être aussi bien un serveur Apache configuré pour gérer PHP qu’un serveur applicatif comme Tomcat.
Si vous voulez installer Nginx pour écouter sur le port 80 (ou 443 pour HTTPS), il va falloir d’abord configurer Apache pour écouter sur d’autres ports.
Changez les ports sur lesquels écoute Apache
Tomcat écoute sur le port 8080. Pour éviter tout conflit, je vous propose de configurer Apache pour écouter sur les ports :
7080 pour le HTTP (au lieu de 80) ;
7443 pour le HTTPS (au lieu de 443).
Changez les numéros de port en conséquence dans le fichier /etc/apache2/ports.conf
, et la configuration de vos virtual hosts dans /etc/apaches/sites-available/
, puis redémarrez Apache :
$ sudo systemctl restart apache2
Installez le serveur web Nginx
Vous pouvez maintenant installer Nginx par la commande suivante :
$ sudo apt install nginx
Vous trouverez alors la configuration de Nginx dans /etc/nginx
. Le fichier de configuration principal est nginx.conf
. Vous y trouvez des directives simples comme :
user www-data;
qui définit l’utilisateur auquel appartient Nginx. Il y a également des “blocs” tels que le bloc http{}
:
http { ... }
qui définit la configuration générale du serveur, et contient tout un tas de directives simples.
Comme pour Apache, les lignes commençant par un #
sont des commentaires, et la configuration inclut les fichiers :
/etc/nginx/conf/*.conf
/etc/nginx/modules-enables/*.conf
/etc/nginx/sites-enabled/*
Passez maintenant à la configuration de vos sites dans /etc/nginx/sites-available
.
Configurez Nginx
Dans Nginx, les “virtual hosts” s’appellent des “server blocs” car ils sont configurés dans des blocs server{}. Commencez par créer le fichier /etc/nginx/sites-available/01-www.example.com.conf
. Il permettra de joindre Jenkins et Apache et il contient :
upstream backend_jenkins{ server 127.0.0.1:8080; } upstream backend_apache{ server 127.0.0.1:7080; } server { listen 80; server_name www.example.com example.com; location /jenkins { include proxy_params; proxy_pass http://backend_jenkins; } location / { include proxy_params; proxy_pass http://backend_apache; } }
upstream backend_jenkins{} | définit un bloc “upstream” dont le nom est backend_jenkins. Ce bloc contient les adresses des serveurs de backend. Si plusieurs adresses sont configurées (une directive server par ligne), Nginx va automatiquement répartir la charge entre ces serveurs |
server {} | c’est l’équivalent du <VirtualHost /> d’Apache, c’est dans ce bloc que vous allez configurer votre site |
listen | spécifie l’IP et le port correspondant |
server_name | précise les domaines valables pour ce site. Plusieurs domaines peuvent être précisés, séparés par des espaces |
location /jenkins {} | précise les règles qui s’appliquent aux adresses qui commencent par “/jenkins” (après le nom de domaine), comme http://www.example.com/jenkins |
proxy_pass http://backend_jenkins; | indique d’agir en tant que proxy et de transmettre les requêtes avec le protocole HTTP vers les serveurs définis dans le bloc upstream “backend_jenkins” |
include proxy_params; | inclut les directives présentes dans le fichier /etc/nginx/proxy_params |
Le fichier proxy_params
contient les directives les plus courantes pour les proxy web. Elles indiquent les en-têtes HTTP à transmettre :
$ cat /etc/nginx/proxy_params proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
En particulier, l’en-tête Host
va permettre à Apache de savoir à quel virtual host transmettre la requête. Les autres requêtes vont permettre à Apache de savoir que c’est un proxy qui transmet les requêtes, et de connaître la véritable IP des clients. Sans ça, Apache s’imaginerait que toutes les requêtes viennent de 127.0.0.1 !
Il vous reste alors à activer votre "server block" en faisant un lien symbolique vers le répertoire sites-enabled
, et à recharger Nginx pour prendre en compte votre configuration :
$ sudo ln -s /etc/nginx/sites-available/01-www.example.com.conf /etc/nginx/sites-enabled/01-www.example.com.conf $ sudo systemctl reload nginx
Enfin, même si Apache reçoit maintenant la véritable IP des clients dans l’en-tête X-Forwarded-For
, il reste à installer le module rpaf
pour que cette IP apparaisse dans les logs en tant qu’IP source des requêtes (et non 127.0.0.1) :
$ sudo apt install libapache2-mod-rpaf $ systemctl restart apache2
Voilà, maintenant vous aurez bien l’adresse réelle de vos clients dans vos logs Apache. :)
Au final, dans la configuration ci-dessus, toutes les requêtes vers www.example.com commençant par /jenkins seront redirigées vers l’application Jenkins hébergée par Tomcat, et toutes les autres adresses seront redirigées vers Apache.
![Capture d'écran d'un navigateur client se connectant à l'adresse http://www.example.com/jenkins et affichant la page d'accueil de Jenkins](https://user.oc-static.com/upload/2018/07/02/15305661044231_02-accueil_jenkins_port_80.png)
La dernière chose qui reste à configurer, c’est de passer les sites en HTTPS pour sécuriser les connexions avec les clients.
Configurez Nginx pour utiliser HTTPS
Vous avez déjà vu comment créer des certificats signés par Let’s Encrypt. Je vais donc vous montrer maintenant la configuration à appliquer pour les utiliser avec Nginx. Votre fichier /etc/nginx/sites-available/01-www.example.org.conf
devrait ressembler à ça :
upstream backend_jenkins{ server 127.0.0.1:8080; } upstream backend_apache{ server 127.0.0.1:7080; } server { listen 80; server_name www.example.com example.com; #Redirige toutes les requêtes http vers https return 301 https://$host$request_uri; } server { listen 443 ssl; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem location /jenkins { include proxy_params; proxy_pass http://backend_jenkins; } location / { include proxy_params; proxy_pass http://backend_apache; } }
Les blocs
upstream{}
ne changent pas.Le bloc
server{}
pour le port 80 contient juste une directive pour rediriger les requêtes en HTTPS.Dans le bloc
server{}
pour le port 443, la directivelisten
précisessl
en plus du port, et les directivesssl_certificate
etssl_certificate_key
indiquent les fichiers certificats à utiliser.
En rechargeant la configuration Nginx, vous pouvez maintenant vous connecter à vos fichiers Apache à l’adresse https://www.example.com/ et à Jenkins par l’adresse https://www.example.com/jenkins .
Obligez vos clients à passer par votre proxy
Vous pouvez maintenant utiliser votre proxy pour vous connecter à vos backends, mais il est toujours possible pour vos clients de se connecter directement à vos backends. En général, c’est quelque chose qu’on cherche à éviter d’un point de vue sécurité. Il est donc très important de configurer vos backends pour n’autoriser les connexions que depuis votre proxy.
Ici, votre proxy et vos backends sont sur la même machine, donc une manière simple de faire ça est de ne les faire écouter que sur l’interface locale 127.0.0.1. Dans d’autres configurations, vous pourriez par exemple utiliser un pare-feu.
Pour Apache, mettez à jour vos fichiers /etc/apache2/ports.conf
et /etc/apache2/sites-available/01-www.example.com.conf
pour remplacer par exemple tous les 7080 par des 127.0.0.1:7080 (idem pour les 7443). Ensuite, redémarrez Apache.
Pour la configuration de Jenkins, vous allez utiliser votre première valve Tomcat.
Une valve Tomcat va permettre d’agir comme un préprocesseur pour chaque requête. Elle va donc faire ses traitements entre la réception de la requête et l’émission de la réponse.
Vous trouverez, entre autres, les valves suivantes :
La valve de journal d’accès : org.apache.catalina.valves.AccessLogValve.
La valve de filtre d’adresse distante : org.apache.catalina.valves.RemoteAddrValve.
La valve de filtre d'hôte distant : org.apache.catalina.valves.RemoteHostValve.
La valve de dump : org.apache.catalina.valves.RequestDumperValve.
Dans notre situation, nous allons utiliser la valve de filtre d’adresse distante (RemoteAddrValve).
Pour Jenkins, vous allez créer un fichier “context”, comme vous l’avez fait pour l’application Manager. Copiez le fichier context du Manager pour créer celui de Jenkins :
$ cd /etc/tomcat8/Catalina/localhost $ cp manager.xml jenkins.xml
Éditez ensuite la balise <Context />
du fichier jenkins.xml
comme ceci :
<Context path=”/jenkins” docBase=”jenkins” > <Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”127.0.0.1” /> </Context>
Il ne vous reste plus qu’à redémarrer Tomcat.
En résumé
Un reverse-proxy est une application qui joue le rôle d’intermédiaire entre des clients et des applications backend.
Le serveur web Nginx est couramment employé en tant que reverse-proxy.
La configuration de Nginx est différente de celle d’Apache. Elle est composée de blocs de directives.
La sécurité est renforcée quand tous les accès passent par le reverse-proxy, et que les accès directs au backend sont bloqués.
Dans le prochain chapitre, vous allez découvrir une autre forme de proxy : le proxy-cache.