Couplage Apache HTTP et Tomcat

Steve Hostettler

Cet article explique comment intégrer le moteur de servlet Apache-Tomcat et le serveur Apache-HTTP, afin de sécuriser (HTTPS) une application Inter/intranet, de faciliter l'accès à cette application par l'utilisation de noms simplifiés (Rewriting) et enfin permettre une tolérance aux pannes (failover) et une répartition de charge (load-balancing).

- Titre : Couplage Apache HTTP et Tomcat

- Auteur : Steve Hostettler

- Parution : 20 février 2006

- Mise à jour : 23 février 2020

- Licence : Copyright © 2006 S. Hostettler (zekey) . Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- Introduction

- I. Trouver les logiciels

- I-A. Apache-Tomcat (Servlet Engine)

- I-B. Apache-HTTPD (Web-Server)

- I-C. Open-SSL

- I-D. Module Apache mod_jk

- I-E. Module Apache mod_ssl

- II. Installation du moteur de servlet Apache-Tomcat

- III. Installation du serveur Web Apache

- IV. Installation du connecteur mod_jk

- V. Installation du mod_rewrite

- VI. Installation de ssl

- VII. Configurer la répartition de charge et le fail-over grâce à Apache

- VIII. Conclusion

Introduction

Lors de la mise en production d'une application Internet ou intranet, il est fréquent de vouloir protéger les transferts par une connexion sécurisée (HTTPS). Même si Tomcat le permet (il suffit d'activer une option dans le server.xml de Tomcat), utiliser Apache est un meilleur choix du fait de sa vitesse. De plus l'utilisation d'Apache permet de se débarrasser des :8080 et autres numéros de ports dans l'url, du fameux « /MonApp » à la fin de ladite url et il offre une intégration plus aisée dans un environnement avec charge répartie (Load Balancing).

I - Trouver les logiciels

Dans un premier temps nous allons nous procurer les logiciels nécessaires.

I-A - Apache-Tomcat (Servlet Engine)

Les binaires de Tomcat peuvent être trouvés ici : http://tomcat.apache.org/download-55.cgi#5.5.12.
Attention la version 5.5 est par défaut compilée avec le JDK 5.0, si vous souhaitez rester en JDK 1.4, prenez une version 5.0.x

I-B - Apache-HTTPD (Web-Server)

Apache est un programme écrit en C, ce qui impose de prendre une distribution compilée pour votre système.
Les binaires pour Windows et les sources pour Unix sont disponibles ici : http://httpd.apache.org/download.cgi. À noter que si vous souhaitez activer le cryptage SSL, il vous faudra soit compiler le module SSL, soit trouver un Apache précompilé avec le support mod_ssl.
Cela vous le trouverez ici : http://brandleadershipmarketing.com/apache/Apache_2.0.55-Openssl_0.9.8a-Win32.zip.
Il existe un substitut au mod_ssl c'est : http://www.apache-ssl.org. Dans le cas où vous seriez sous Linux/Unix la seule autre possibilité est la compilation :-D.

I-C - Open-SSL

Nous allons devoir générer un certificat pour notre Apache, il nous faut donc les outils openSSL que vous trouverez ici :
http://brandleadershipmarketing.com/apache/Openssl-0.9.8a-Win32.zip.

I-D - Module Apache mod_jk

C'est ce petit module qui va faire le lien entre Apache et Tomcat, vous en trouverez des binaires ici : http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/. Prenons par exemple la version pour Windows 32 bits : mod_jk_1.2.6_1.3.31.dll.

I-E - Module Apache mod_ssl

Ce dernier point n'est nécessaire que si votre version d'Apache ne l'intègre pas en standard (pas compilé en interne) ou si vous n'avez pas pris le binaire cité plus haut.

II - Installation du moteur de servlet Apache-Tomcat

L'installation du moteur de servlet Apache-Tomcat est vraiment aisée. Il existe deux méthodes :

1. Par un installer ;

2. En décompressant un fichier zip.

Je préfère la deuxième car :
- elle n'induit pas de dépendances externes du type base de registre ;
- c'est un processus identique sur tous les systèmes d'exploitation et, de ce fait c'est plus automatisable.

Si vous choisissez la méthode de la décompression, prenez cependant garde d'avoir configuré convenablement les variables d'environnement. JAVA_HOME étant la plus importante.

Pour ce faire :

sous Linux/Unix :

export JAVA_HOME=/opt/Java50

sous Windows :

set JAVA_HOME=C:\j2ee\Java50

Pour plus d'informations sur l'installation de Tomcat : https://wpetrus.developpez.com/java/tomcat/windows/.

III - Installation du serveur Web Apache

L'installation du serveur Web-Apache se fera sous Windows presque toujours par un installer, donc laissez-vous guider. Sous Unix/Linux, il faudra soit le recompiler, soit trouver un package ou un rpm tout prêt.

À présent, vous devez tester ce que vous avez installé, car il est inutile d'aller plus loin si ça ne marche pas. Essayez de vous connecter sur http://localhost:8080, vous devriez voir la fenêtre de tomcat, et sur http://localhost celle d'Apache-HTTP.

IV - Installation du connecteur mod_jk

Commençons par le plus simple, relier Apache et Tomcat.
Pour cela prenez le binaire (par exemple mod_jk_1.2.6_1.3.31.dll pour Windows ou jakarta-tomcat-connectors-jk-1.2.6-linux-fc2-i386-apache-2.0.50.so pour Linux) et renommez le binaire en mod_jk.dll ou mod_jk.so.
Ensuite, décompressez le fichier dans un répertoire et copiez le fichier mod_jk.dll ou .so dans le répertoire modules présent dans l'arborescence d'Apache. Puis dans le répertoire conf d'Apache créez un fichier worker.properties contenant :

$APACHE_HOME/conf/worker.properties

ps=/
worker.list=default
worker.default.port=8009
worker.default.host=127.0.0.1
worker.default.type=ajp13

Dans ce fichier, normalement la seule chose que vous ayez à changer est la ligne worker.default.host=127.0.0.1 dans laquelle vous pouvez spécifier l'adresse IP du serveur Tomcat s'il est distant. Notez que le port 8009 doit être accessible au serveur Apache, c'est-à-dire pas de firewall au milieu ou alors il faut configurer ledit firewall.

Puis, nous allons configurer Apache pour lui faire prendre en compte notre module : éditez le ficher httpd.conf présent dans le sous-répertoire conf d'Apache. Recherchez un ensemble de lignes du type LoadModule et à la fin de cette partie ajoutez

$APACHE_HOME/conf/httpd.conf

[...]
LoadModule jk_module modules/mod_jk.dll

#
# Mod_jk settings
#
JkWorkersFile "C:/J2EE/Apache2/Apache2/conf/worker.properties"
JkLogFile "C:/J2EE/Apache2/Apache2/logs/mod_jk.log"
JkLogLevel warning
JkMount /j2ee default
JkMount /j2ee/* default
# End of mod_jk settings
[...]

Comme vous pouvez le voir, ce n'est pas bien compliqué. La première ligne active le module, puis nous donnons des informations au module, naturellement ici vous devez mettre des chemins qui correspondent à votre installation d'Apache. Enfin notez les deux lignes qui commencent par JkMount, à la place de tomcat-docs (qui est une application installée par défaut sur Tomcat) vous devez mettre le nom de l'application web que voulez mapper. C'est-à-dire celle qui doit être accessible sur le serveur Apache-HTTP.

Démarrez Tomcat et Apache et essayez d'accéder à une application. En cas de problème vous pouvez regarder le contenu des messages dans le répertoire logs d'Apache.

À présent vous devez pouvoir vous connecter, non plus en faisant : http://mon_server_tomcat:8080/tomcat-docs,
mais en faisant: http://mon_serveur_apache/tomcat-docs.

V - Installation du mod_rewrite

L'objectif est de supprimer la partie droite de l'url à savoir dans notre cas tomcat-docs. Pour cela nous allons rediriger toutes les requêtes à destination de / vers /tomcat-docs. Donc il nous faut activer le module mod_rewrite qui peut être soit un module, soit compilé en standard.

Sous Windows c'est un module, mais qui est activé par défaut :
LoadModule rewrite_module modules/mod_rewrite.so Vérifiez donc que la ligne n'est pas en commentaire et, à la fin du fichier httpd.conf, ajoutez ou complétez :

[...]
<VirtualHost *:80>
RewriteEngine On
RewriteRule ^$ http://localhost/tomcat-docs  [L]
</VirtualHost>
[...]

Il est à noter que localhost doit être le nom de la machine que vous utilisez pour vous connecter, donc en production ce sera certainement plus quelque chose du genre : www.company.com, car Apache reconnaît de façon différente des requêtes qui arrivent sur www.company.com et sur localhost même s'il s'agit physiquement de la même machine De plus lors de l'utilisation de ssl ce sera indispensable du fait du nom de domaine présent dans le certificat.

Maintenant vous pouvez redémarrer Apache et vous connecter sur http://localhost qui devrait vous rediriger automatiquement vers l'application web.

VI - Installation de ssl

C'est ici qu'il vous faudra le plus de patience, donc allez boire un café, détendez-vous et c'est parti. Décompressez Open-SSL dans un répertoire. Ouvrez une fenêtre de commande sous Windows ou un shell sous Linux.

Maintenant nous allons générer un certificat pour ssl. Attention ce n'est pas un certificat officiel donc vous ne bénéficierez d'aucune assurance ou couverture légale, pour cela il faut acheter un certificat chez une autorité compétente, mais en tous les cas la sécurité du cryptage sera presque la même.

Nous allons créer un .sh ou .bat dans le répertoire concerné :

sh ou cmd

#cat csr.bat
openssl req -config openssl.conf -new -out site.csr
openssl rsa -in privkey.pem -out site.key
openssl x509 -in site.csr -out site.cert -req -signkey site.key -days 365
openssl x509 -in site.cert -out site.der.crt -outform DER

Voici un exemple de fichier openssl.conf :

# SSLeay example configuration file.
# This is mostly being used for generation of certificate requests.
#
# Original source unknown.
# Modified 2003-02-07 by Dylan Beattie (openssl@dylanbeattie.net)
# http://www.dylanbeattie.net/docs/openssl_iis_ssl_howto.html

RANDFILE      = .rnd

####################################################################
[ ca ]
default_ca   = CA_default      # The default ca section

####################################################################
[ CA_default ]

certs      = certs         # Where the issued certs are kept
crl_dir      = crl         # Where the issued crl are kept
database   = database.txt      # database index file.
new_certs_dir   = certs         # default place for new certs.

certificate   = cacert.pem          # The CA certificate
serial      = serial.txt       # The current serial number
crl      = crl.pem       # The current CRL
private_key   = private\cakey.pem      # The private key
RANDFILE   = private\private.rnd    # private random number file

x509_extensions   = x509v3_extensions   # The extentions to add to the cert
default_days   = 365         # how long to certify for
default_crl_days= 30         # how long before next CRL
default_md   = md5         # which md to use.
preserve   = no         # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy      = policy_match

# For the CA policy
[ policy_match ]
countryName      = match
stateOrProvinceName   = match
organizationName   = match
organizationalUnitName   = match
commonName      = supplied
emailAddress      = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName      = optional
stateOrProvinceName   = optional
localityName      = optional
organizationName   = optional
organizationalUnitName   = optional
commonName      = supplied
emailAddress      = optional

####################################################################
[ req ]
default_bits      = 1024
default_keyfile    = privkey.pem
distinguished_name   = req_distinguished_name
attributes      = req_attributes

[ req_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_min         = 2
countryName_max         = 2
stateOrProvinceName      = State or Province Name (full name)
localityName         = Locality Name (eg, city)
0.organizationName      = Organization Name (eg, company)
organizationalUnitName      = Organizational Unit Name (eg, section)
commonName         = Common Name (eg, your website's domain name)
commonName_max         = 64
emailAddress         = Email Address
emailAddress_max      = 40

[ req_attributes ]
challengePassword      = A challenge password
challengePassword_min      = 4
challengePassword_max      = 20

[ x509v3_extensions ]
# under ASN.1, the 0 bit would be encoded as 80
# nsCertType         = 0x40
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
#nsCertSequence
#nsCertExt
#nsDataType

Cela va créer un certificat valable un an. Attention les informations que vous donnerez et surtout le nom du serveur doivent être corrects sinon le certificat sera refusé. Dans le même répertoire seront générés les fichiers suivants :

(copiez ces fichiers dans le répertoire Apache/conf et éditez le fichier httpd.conf)

1. site.der.crt ;

2. site.key.

Commencez par activer ou saisir la ligne LoadModule jk_module modules/mod_jk.dll ou mod_jk.so puis il faut s'assurer que Apache écoute sur le port 443 (le port https) pour cela cherchez :

[...]
#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
#
[...]

et ajoutez :

[...]
Listen localhost:80
Listen localhost:443
[...]

Attention localhost doit être le nom avec lequel vous interrogez la machine et avec lequel vous avez créé votre certificat.

Puis cherchez

[...]
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If this is not set to valid DNS name for your host, server-generated
# redirections will not work.  See also the UseCanonicalName directive.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
# You will have to access it by its address anyway, and this will make
# redirections work in a sensible way.
#
ServerName localhost
[...]

Même remarque que précédemment concernant le nom du serveur.

Enfin, à la fin du fichier remplacez le bloc que nous avons saisi en V par :

[...]
NameVirtualHost *:80
NameVirtualHost *:443

<VirtualHost *:80>
RewriteEngine On
#Nous redirigeons toutes les requêtes qui ne sont pas sécurisées vers le port 443 (HTTPS)
RewriteCond %{SERVER_PROTOCOL} !^HTTPS
RewriteRule ^(.*)$ https://localhost/tomcat-docs/$1 [R,L]

</VirtualHost>

<VirtualHost *:443>
#Activation de SSL, remarquez le nom des fichiers
SSLEngine On
SSLCertificateFile conf/site.cert
SSLCertificateKeyFile conf/site.key
#Ici nous faisons, ce que nous faisions au paravent en http, c'est-à-dire rediriger les requêtes de / vers /tomcat-docs
RewriteEngine On
RewriteRule ^$ https://localhost/tomcat-docs  [L]

</VirtualHost>
[...]

Il est important de noter que dans cet exemple, seul l'hôte localhost fonctionnera, ce qui est un dommage pour une application web. Il faut remplacer « localhost » par un nom convenable.

VII - Configurer la répartition de charge et le fail-over grâce à Apache

Apache permet de répartir la charge entre plusieurs Tomcats, cette répartition permet également de gérer la redondance. Pour ce faire nous allons simplement étendre la gestion par le mod_jk de la façon suivante :

$APACHE_HOME/conf/worker.properties

ps=/
#La liste des tomcat qui renter dans notre load-balancer, plus l'alias sur le load-balancer
worker.list=node1, node2, loadbalancer

#Le premier tomcat
worker.node1.port=8009
worker.node1.host=127.0.0.1
worker.node1.type=ajp13

#Le second Tomcat, attention soit l'hôte soit le port doivent différés
worker.node2.port=9009
worker.node2.host=127.0.0.1
worker.node2.type=ajp13

#La config du load-balencer
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=node1, node2

En fait, nous nous contentons de définir la liste des tomcats qui rentrent dans la liste des serveurs à équilibrer (balancer).

Pour tester, il faut installer un second Tomcat. Idéalement, faites-le sur une autre machine ou, à défaut, sur la même.

Si ce nouveau Tomcat est sur la même machine, il faut changer le numéro du port sur lequel il écoute. Tomcat écoute sur plusieurs ports, notamment par défaut le 8080 (celui que l'on utilise en développement) et le port AJP13 qui lui permet de se connecter avec Apache. Pour cela, éditez le fichier « server.xml » et changez les ports sur lesquels il écoute :

[...]
<Server port="9005" shutdown="SHUTDOWN">
<Connector port="9090" maxHttpHeaderSize="8192"
<Connector port="9443" maxHttpHeaderSize="8192"
<Connector port="9009" enableLookups="false" redirectPort="9443" protocol="AJP/1.3" />
<Connector port="9082"  maxThreads="150" minSpareThreads="25" axSpareThreads="75" />
[...]

Il est important de noter que seul le port AJP13 (9009 dans notre cas, mais 8009 par défaut) est important. Les autres changements évitent que Tomcat ne plante au démarrage et peuvent, le cas échéant (en production), même être désactivés.

VIII - Conclusion

Nous avons vu comment lier Tomcat et Apache-HTTP ensemble, pour permettre de sécuriser une application Intra/Internet, facilitant l'accès aux utilisateurs grâce à des noms plus courts. Enfin nous avons configuré un load-balancing « logiciel » qui réduit le temps d'indisponibilité de vos applications et améliore leur montée en charge.

Si vous rencontrez des problèmes, ou si vous avez des questions ou des remarques, n'hésitez pas à m'écrire. Rendez-vous sur le forum Java/J2EE sur https://www.developpez.net