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 la dite url et enfin la possibilité 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. A 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 une alternative au mod_ssl c'est : http://www.apache-ssl.org. Dans le cas où vous seriez sous Linux/Unix la seule alternative 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:

 
Sélectionnez

export JAVA_HOME=/opt/Java50

Sous Windows:

 
Sélectionnez

set JAVA_HOME=C:\j2ee\Java50

Pour plus d'informations sur l'installation de Tomcat: http://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.

A 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
Sélectionnez

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 le dit firewall.

Puis, nous allons configurer Apache pour le 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
Sélectionnez

[...]
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 2 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.

A 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 :

 
Sélectionnez

[...]
<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çons différentes 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égales, 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
Sélectionnez

#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 :

 
Sélectionnez

 
# 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 editez 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 :

 
Sélectionnez

[...]
#
# 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 :

 
Sélectionnez
			
[...]
Listen localhost:80
Listen localhost:443
[...]

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

Puis cherchez

 
Sélectionnez

[...]
#
# 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 :

 
Sélectionnez

[...]
NameVirtualHost *:80
NameVirtualHost *:443
 
<VirtualHost *:80>
        RewriteEngine On
#Nous redirigeons toutes les requetes qui ne sont pas sécurisés 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ête 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
Sélectionnez

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 rentre dans la liste des serveurs à équilibrer(balancer).

Pour tester il faut installer un second Tomcat. Idéalement faîtes-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 developpement) 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 :

 
Sélectionnez

[...]
<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 ensemble 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és 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 http://www.developpez.net