vendredi 24 septembre 2010

Rediriger des requêtes de Apache vers Tomcat

Il est d'usage de ne pas exposer son serveur Tomcat (server Servlet+JSP) à l'insécurité régnant sur le WEB. On considère, à juste titre sans doute, que ce bel édifice Java a la cuirasse un peu fine pour survivre bien longtemps au flot de requêtes plus ou moins bienveillantes qui s'abat immédiatement sur tout serveur référencé par Google.
Il n'en est pas de même pour son grand frère Apache qui résiste à tout du moment que son administrateur ait survécu aux affres de la configuration.
Une fois cela posé, on comprend pourquoi les applications Java sont habituellement servies par un serveur Tomcat causant sur un port privé (8080 par exemple) et s'abritant derriere un serveur Apache causant sur sur le classique port 80.
La question est de savoir comment dire à Apache de rediriger correctement les requêtes destinées à Tomcat.
Il existe deux méthodes: Le proxy et AJP.

Le proxy:
Cette méthode n'est pas dédiées à Tomcat. Elle peut être utilisée pour rediriger des requêtes vers n'importe quel serveur HTTP. Tout se passe au niveau du fichier de config d'Apache httpd.conf (habituellement dans /etc/httpd/conf sous Linux).

1) S'assurer que les bon modules sont chargés: Vérifier que les modules suivants sont bien dans /etc/httpd/modules, sinon les charger avec yum, apt-get ou même depuis le site apache (http://httpd.apache.org/modules/). Le code de configuration ci-dessous demande à Apache de charger ces modules au démarrage

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so

Supposons que Apache tourne sur une machine nommée frontale et que Tomcat tourne sur une machine nommée tomcat.
Supposons que l'URLeffective de l'application soit http://tomcat:8080/APPLI mais que vue de l'extérieur, elle soit référencée par l'URL http://frontale/appli. Supposons également que cette application utilise des cookies.
Il suffit d'insérer le bloc suivant dans le fichier httpd.conf et de relancer Apache (et Tomcat)

ProxyPass /appli http://tomcat:8080/APPLI
ProxyPassReverse /appli http://tomcat:8080/APPLI
ProxyPassReverseCookiePath /APPLI /appli
ProxyPassReverseCookieDomain tomcat frontale

Cette méthode est très simple mais elle n'est pas très performante car elle demande à Apache de transférer tous les paquets d'un serveur HTTP à un autre (transfert a niveau application). Cela demande une double prise en charge du protocole HTTP.

Il est bien plus efficace d'effectuer le transfert des paquets TCP/IP au niveau des sockets directement. Tomcat implémente par défaut un serveur de sockets (port 8009) dédié cette fonction. Apache dispose d'un module (mod_jk) effectuant ce transfert. C'est le protocole AJP (version 1.3). Il est implémenté par la plus part des serveusr HTTP et des serveurd d'applications.

La méthode AJP:

L'idée est de déclarer un connecteur nommé (monworker dans notre exemple) qui sera en charge des redirections pour une ou plusieurs applications. Dans l'exemple ci-dessous, on suppose que Tomcat et Apache tournent sur le même serveur.

Il faut d'abord configurer Tomcat pour qu'il charge le module mod_jk au démarrage:

LoadModule jk_module modules/mod_jk-1.2.30-httpd-2.0.X.so

Vérifier que le module est bien dans /etc/httpd/modules, sinon le charger avec yum, apt-get ou depuis le site apache (http://mirror.mkhelif.fr/apache//tomcat/tomcat-connectors/jk/binaries/).

Il faut ensuite déclarer le connecteur (worker) dans un fichier. Ce fichier est habituellement localisé dans /etc/httpd/conf/workers.properties.

worker.list=monworker
worker.monworker.port=8009
worker.monworker.host=localhost
worker.monworker.type=ajp13

Dans notre exemple, le nom du worker est monworker, il utilise le port 8009, il est hébergé sur la machine locale et il utilise le protocole AJP 1.3.

Il faut ensuite donner quelques indications à Tomcat pour qu'il utilise le module AJP.
Les règles suivantes sont à mettre dans httpd.conf. Elles parlent d'elles mêmes.

JkWorkersFile /etc/httpd/conf/workers.properties
JkLogFile /var/log/httpd/mod_jk.log
JkShmFile /var/log/httpd/mod_jk.shm
JkLogLevel info

Une fois cela fait il ne reste plus qu'à déclarer un hôte virtuel pour mon application Tomcat dans httpd.conf:

JkMount /appli monworker
JkMount /appli/* monworker

Noter que dans ce cas, l'application garde le même nom (appli).
Une fois cela fait et les serveurs redemarrés, les requête du type http://frontale/appli/.. seront exécutées par Tomcat comme http://frontale:8080/appli/..

On verra plus tard comment comment faire avec deux serveurs distincts.