Introduction
Dans ce poste je décrirai comment faire écouter Tomcat 5.5 sur le port privilégié 80, sans Apache, et de façon sécurisée.
La sécurité et le port 80
L'installation par défaut de Tomcat 5.5 sous Ubuntu est sécurisée dans le sens qu'il tourne en tant que l'utilisateur non-privilégié $TOMCAT5_USER, dont la valeur est définie dans le fichier /etc/default/tomcat5.5. Ceci est important, vu que Tomcat lance une machine virtuelle Java, fonctionnellement capable de tout sur votre serveur. En le lançant en tant qu'un utilisateur normal, on peut limiter les dommages qu'un détournement du JVM pourrait causer par l'intermédiaire du système de permissions Linux.
L'inconvénient de cet installation sécurisée est tout simplement le fait qu'uniquement l'utilisateur priviligié root peut acquêrir les ports dans l'intervalle 1-1024. Or, cela comprend le port 80, utilisé par défaut par le protocole HTTP. Ce qui mène à devoir choisir entre la sécurité et l'accéssibilité.
La solution Apache
Jusqu'à récemment, la seule moyenne de rendre Tomcat sûr et accessible était de passer par Apache. Apache, le serveur web gratuit et performant, est, lui, capable de tourner de façon sécurisée sur le port 80. Ceci est possible grâce à une lancement en deux étapes: (1) aquêrir le port 80 en tant que root et (2) exécuter le daemon du serveur en tant qu'un utilisateur normal. Une fois installé sur le port 80, Apache, par l'intermédiaire d'une architecture de connectors, peut faire suivre les requêtes destinées aux ressources JSP et Servlet au serveur Tomcat, qui lui tourne doucement en tant qu'un utilisateur non-priviligié sur un port au-delà de 1024.
Pour les développeurs voulant travailler principalement avec un contenu dynamique, cet approche pose deux inconvénients:
- Tomcat peut servir un contenu statique aussi bien qu'Apache, et s'est prouvé très fiable dans ce role. Faire tourner Apache et Tomcat introduit donc une certaine redondance.
- Connecter Apache et Tomcat est délicate, demande une installation plus complexe, et rende plus longue la chaîne de traitement des reqûetes JSP et Servlets.
La solution jsvc
Une nouvelle solution est récemment apparue, dans la forme de l'application jsvc. Cette application permet à un utilisateur normal de lancer un programme Java comme un daemon sur un port priviligié. Le lancement de jvsc, comme Apache, se fait en deux étapes: Il aquêre le port en tant que root, et ensuite lance le JVM et le programme Java en tant que l'utilisateur non-privilegié. jsvc permet ainsi d'atteindre une solution semblable à celle permise par Apache, sans le besoin de passer par Apache.
Apache reste une solution interéssant quand vous voulez héberger plusieurs sites web sur le même addresse IP, chacune dans une instance Tomcat différente. Pusique deux daemons ne peuvent pas écouter sur le même port, il est donc impossible de lancer plusieurs instances Tomcat sur le port 80. Dans ce cas, Apache, avec son système de connectors permet de héberger plusieurs hôtes virtuels sur le port 80, et de diriger une requête pour un hôte vers son instance Tomcat. J'en parlerai dans un poste futur.
Installer jsvc
Pour installer jsvc sous Ubuntu 6.10, j'utilise apt-get:
$ sudo apt-get install jsvc
Le paquet se trouve dans la catégorie universe. Mettre à jour les catégories parcourues dans /etc/apt/sources.list si apt-get ne trouve pas le paquet.
(Re)Configurer Tomcat
J'effectue deux modifications à l'installation par défaut de Tomcat:
1) Je vais faire tourner Tomcat en tant que l'utilisateur non-privilégié $TOMCAT5_USER (tomcat5 sur mon système). Afin d'être sûr que cet utilisateur aura accès à tous les fichiers Tomcat, je lui désigne propriétaire de tous les répertoires et fichiers de mon serveur et mon instance, et je lui y accord les droits de lecture et écriture:
$ sudo chown -R -L tomcat5 $CATALINA_HOME $CATALINA_BASE
$ sudo chmod -R 755 $CATALINA_HOME $CATALINA_BASE
2) Je configure mon instance pour qu'il ecoute sur le port 80, au lieu du port par défaut, le 8180. Dans le fichier ${CATALINA_BASE}/server.xml, j'identifie les lignes suivantes ...
<Service name="Catalina">
...
<Connector
port="8180"
redirectPort="8443"
minSpareThreads="25"
...
... et je remplace la valeur 8180 par 80.
Le script daemon
Pour que Tomcat peut aquêrir le port 80, je dois le lancer avec jsvc. Le script ci-dessous fait exactement cela. Il est basé sur le script daemon fournit avec Tomcat 5.5, et s'utilise de la même manière. Copier-le et enregistrer-le dans un fichier /etc/init.d/tomcat5.5-priv en tant que root.
#!/bin/sh
#
# /etc/init.d/tomcat5.5-priv
# -- startup script for running Tomcat 5.5 on ports 1-1024
#
# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
# Modified for Debian GNU/Linux by Ian Murdock <imurdock@gnu.ai.mit.edu>.
# Modified for Tomcat by Stefan Gybas <sgybas@debian.org>.
# Modified for Ubuntu 6.10 Edgy by Justin Templemore <justin@thedancer.org>.
#
# If you want to have Tomcat running on port 80 don't forget to modify the instance
# configuration file in ${CATALINA_BASE}/conf/server.xml:
#
# <!-- Define a non-SSL HTTP/1.1 Connector on port 80 -->
# <Connector className="org.apache.catalina.connector.http.HttpConnector"
# port="80" minProcessors="5" maxProcessors="75"
# enableLookups="true" redirectPort="8443"
# acceptCount="10" debug="0" connectionTimeout="60000"/>
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
SERVER_NAME=tomcat5.5
INSTANCE_NAME=tomcat5.5
DESC="Privileged Tomcat 5.5 servlet engine"
CATALINA_HOME=/usr/share/${SERVER_NAME}
DEFAULT=/etc/default/${INSTANCE_NAME}
# Load Tomcat default settings
if [ -f "$DEFAULT" ]; then
. "$DEFAULT"
fi
# Override the Tomcat defaults as required for this instance
# Set the JVM installation to use
JAVA_HOME=/usr/lib/jvm/java-6-sun
# Run Tomcat 5 as this user ID
TOMCAT5_USER=tomcat5
# Use the Java security manager? (yes/no)
TOMCAT5_SECURITY=yes
# Timeout in seconds for the shutdown of all webapps
TOMCAT5_SHUTDOWN=30
# Directory for per-instance configuration files and webapps. It contain the
# directories conf, logs, webapps, work and temp. See RUNNING.txt for details.
CATALINA_BASE=/var/lib/${INSTANCE_NAME}
if [ `id -u` -ne 0 ]; then
echo "Not starting/stopping $DESC, you are not root."
exit 4
fi
if [ -z "$TOMCAT5_USER" ]; then
echo "Not starting/stopping $DESC as configured (TOMCAT5_USER is"
echo "empty in $DEFAULT)."
exit 0
fi
# Set java.awt.headless=true if CATALINA_OPTS is not set so the
# Xalan XSL transformer can work without X11 display on JDK 1.4+
# It also looks like the default heap size of 64M is not enough for most cases
# se the maximum heap size is set to 128M
if [ -z "$CATALINA_OPTS" ]; then
CATALINA_OPTS="-Djava.awt.headless=true -Xmx128M"
fi
# Set the JSP compiler if set in the tomcat5.5.default file
if [ -n "$JSP_COMPILER" ]; then
CATALINA_OPTS="$CATALINA_OPTS -Dbuild.compiler=$JSP_COMPILER"
fi
# Define other required variables
CATALINA_PID="$CATALINA_BASE/temp/${INSTANCE_NAME}.pid"
STARTUP_OPTS=""
if [ "$TOMCAT5_SECURITY" = "yes" ]; then
STARTUP_OPTS="-security"
fi
# Look for Java Secure Sockets Extension (JSSE) JARs
if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
JSSE_HOME="${JAVA_HOME}/jre/"
fi
export CATALINA_HOME CATALINA_BASE CATALINA_OPTS CATALINA_PID JSSE_HOME
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
/usr/share/java/commons-daemon.jar:\
/usr/share/${SERVER_NAME}/bin/bootstrap.jar
case "$1" in
start)
if [ -z "$JAVA_HOME" ]; then
echo "Could not start $DESC because no Java Development Kit"
echo "(JDK) was found. Please download and install JDK 1.3 or higher and set"
echo "JAVA_HOME in $DEFAULT to the JDK's installation directory."
exit 0
fi
if [ ! -d "$CATALINA_BASE/conf" ]; then
echo "Not starting Tomcat 5: Invalid CATALINA_BASE specified in $DEFAULT"
exit 1
fi
echo -n "Starting $DESC using [jsvc] with JVM=$JAVA_HOME: "
if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
--user $TOMCAT5_USER --startas "jsvc" \
>/dev/null; then
jsvc \
-user $TOMCAT5_USER \
-home $JAVA_HOME \
-Dcatalina.home=$CATALINA_HOME \
-Dcatalina.base=$CATALINA_BASE \
-Djava.io.tmpdir=$CATALINA_BASE/temp \
-wait 10 \
-pidfile $CATALINA_PID \
-outfile $CATALINA_HOME/logs/catalina.out \
-errfile '&1' \
$CATALINA_OPTS \
-cp $CLASSPATH \
org.apache.catalina.startup.Bootstrap
#-verbose \
#-debug \
echo "Started."
else
echo "Already running."
fi
;;
stop)
echo -n "Stopping $DESC: "
if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
--user "$TOMCAT5_USER" --startas "jsvc" \
>/dev/null; then
echo "Not running."
else
jsvc \
-stop \
-pidfile $CATALINA_PID \
org.apache.catalina.startup.Bootstrap
#-verbose \
#-debug \
rm -f "$CATALINA_PID" "$CATALINA_BASE/logs/catalina.out"
echo "Stopped"
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
status)
if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
--user $TOMCAT5_USER --startas "jsvc" \
>/dev/null; then
if [ -f "$CATALINA_PID" ]; then
echo "$DESC is not running, but PID file exists."
exit 1
else
echo "$DESC is not running."
exit 3
fi
else
echo -n "$DESC is running as jsvc with PID "
cat "$CATALINA_PID"
exit 0
fi
;;
*)
echo "Usage: /etc/init.d/tomcat5.5-priv {start|stop|restart}" >&2
exit 2
;;
esac
Je le rends exécutable:
$ sudo chmod ugo+x /etc/init.d/tomcat5.5-priv
Et je le lance:
$ sudo /etc/init.d/tomcat5.5-priv start
Starting Shared Tomcat 5.5 servlet engine using [jsvc] with JVM=/usr/lib/jvm/java-6-sun: Started.
Je vérifie le lancement de Tomcat sur le port 80 en pointant mon navigateur sur l'adresse IP de mon serveur. Je devrais voir la page de bienvenue de Tomcat, sinon mes webapps déjà déployées.
Si le daemon ne démarre pas correctement, un bon endroit pour trouver la raison est dans le logfile de démarrage de Tomcat: $CATALINA_BASE/logs/catalina.out
Les deux erreurs les plus probables sont:
- Une erreur dans la variable CLASSPATH: Vérifier bien que les jars indiqués se trouve dans les endroits attendus, sinon mettre à jour le CLASSPATH pour refléter la localisation de ces fichiers sur votre système.
- Un autre programme écoute déjà sur le port 80. Lancez lsof -i :80 pour vérifier que Tomcat écoute bien sur le port 80.
Configuration du lancement et arrêt automatique du daemon
J'utilise l'outil update-rc.d pour configurer le lancement et arrêt automatique de mon daemon Tomcat avec le serveur. Ci-dessous je désinstalle d'abord le daemon originale installé avec Tomcat.
$ sudo update-rc.d -f tomcat5.5 remove
$ sudo update-rc.d tomcat5.5-priv defaults
Consulter le man pour plus d'infos sur la commande update-rc.d.
1 comment:
Il est vrai que Tomcat embarque un serveur HTTP, et peut donc delivrer du contenu statique. Mais en terme de performance, Apache HTTP Server sera plus rapide pour retourner un contenu statique que Tomcat.
Cela vaut donc le coup de se pencher sur l'installation de Tomcat et Apache HTTP Server, meme si on doit galerer un peu, que de foncer tete baissée dans une installation basique de Tomcat.
Post a Comment