TP 1 : technologies côté serveur

Objectifs pédagogiques du TP

Outils

Évaluation

Vous répondrez aux questions numérotées en rouge et en gras de cet énoncé dans le questionnaire Tomuss correspondant à votre groupe : https://tomuss.univ-lyon1.fr/2019/Automne/TP1-M1IF03-grpA ou -grpB ou -grpC ou -grpD. La note de ce TP sera calculée en fonction de vos réponses à ce questionnaire.

Préambule

Attention : vous devez être soit sur eduroam, soit en VPN (soit sur les machines de TP) pour faire la partie PHP.

Pour ce TP, vous utiliserez la ferme de machines virtuelles de l'université. Nous avons préparé une configuration spéciale comprenant une Ubuntu 16.04 serveur (sans window manager) avec un serveur nginx (1.10.1) préinstallé. Ces machines ne sont accessibles que depuis l'intérieur de l'université.

Votre encadrant vous aura assigné une VM par binôme. Cette VM tournera déjà et vous y aurez accès par son adresse IP. Vous vous connecterez dessus en SSH avec l'utilisateur "etudiant/etudiant". Cet utilisateur est dans le groupe de sudoers.

L'adresse IP de votre VM est "192.168.75." plus le numéro de binôme qui vous a été attribué par votre enseignant.

Dans Tomuss, indiquez les 3 derniers chiffres (dernier octet) de cette adresse IP dans la case prévue à cet effet.

L'exécutable nginx est /usr/sbin/nginx et les fichiers de configuration sont dans le répertoire /etc/nginx/. La config de base du serveur est dans le fichier nginx.conf, et celle des sites déployés est déportée dans des fichiers spécifiques.

1. Prise en main d'nginx

Vérifiez que le serveur HTTP nginx de votre VM est lancé et qu'il fonctionne.

Les commandes pour démarrer/arrêter nginx sont détaillées à http://nginx.org/en/docs/beginners_guide.html#control. Alternativement, vous pouvez utiliser la commande sudo service nginx start, stop ou restart.

À l'aide de commandes Unix de base, de la documentation d'nginx et du Web, répondez aux questions suivantes :

  1. Quel est l'utilisateur qui a lancé le serveur ? Pourquoi ?
  2. Quel est l'utilisateur qui fait tourner les "workers" ? Pourquoi ?
  3. Indiquez la fonction des principaux éléments (sous-répertoires, fichiers par thématique) du répertoire de configuration d'nginx.
  4. Que signifie la deuxième ligne (non vide) du fichier nginx.conf et comment vérifier qu'elle est bien prise en compte ?
  5. Où est spécifié le port sur lequel répond le serveur (fichier et directive) ?
  6. Où est situé le fichier de configuration du site actuellement déployé et comment le serveur le "trouve"-t-il ?
  7. Quel est le répertoire où se trouvent les données du site (fichier et directive) ? Pour vérifier, modifiez la page d'accueil de ce site, et constatez le résultat dans le navigateur.

2. Sécurisation du serveur

La première chose que vous allez faire est de passer le serveur nginx en HTTPS.

2.1. Opérations préalables à faire dans le répertoire /home/etudiant :

- générer un fichier de configuration pour le générateur de nombres aléatoires d'openssl

openssl rand -writerand .rnd

ou

openssl rand 4096 > .rnd

- Récupérer les certificats générés par l'aurorité "M1IF03-CAW" : remplacer "XX" par la fin de l'IP de votre VM

curl https://perso.liris.cnrs.fr/lionel.medini/enseignement/M1IF03/Certificats/192.168.75.XX.key > server.key

curl https://perso.liris.cnrs.fr/lionel.medini/enseignement/M1IF03/Certificats/192.168.75.XX.cert > server.cert

Récupérez la configuration additionnelle d'nginx :

curl https://perso.liris.cnrs.fr/lionel.medini/enseignement/M1IF03/Certificats/ssl-params.inc > ssl-params.inc

Placez-vous maintenant dans le répertoire où vous configurerez la couche SSL du serveur.

cd /etc/nginx/
sudo mkdir ssl
cd ssl

2.2. Certificat auto-signé

Création d'une paire de clés RSA sans protection en 2048 bits

sudo openssl genrsa -out ./server.key 2048

Visualisation (la clé privée et la clé publique sont toutes les deux incluses dans ce fichier)

sudo openssl rsa -in ./server.key -noout -text

Génération d'un certificat auto-signé valable 10 ans (remplacer "XX" à la fin de l'IP par celle de votre machine) :

sudo openssl req -key ./server.key -new -x509 -days 3650 -sha256 -out ./server.cert -subj "/C=FR/L=Lyon/O=MIF03-CAW/CN=192.168.75.XX"

Vous devez avoir un fichier .cert dans le répertoire ssl

Pour en visualiser le contenu :

openssl x509 -noout -text -in ./server.cert

Quelles sont les parties de la paire de clés RSA qui constituent la clé publique ?

Pourquoi les contenus des champs Issuer et Subject sont-ils identiques ?

2.3. Modification de la configuration d'nginx

cd ../sites-available/
sudo nano default

Décommenter les deux lignes listen en SSL

Rajouter au-dessous :

ssl_certificate     /etc/nginx/ssl/server.cert;
ssl_certificate_key /etc/nginx/ssl/server.key;

Pour améliorer la sécurité du serveur (voir https://cipherli.st/), copiez le fichier ssl-params.inc (à la racine du compte etudiant) dans le répertoire /etc/nginx/conf.d et rajoutez la ligne suivante après la configuration SSL dans le fichier de configuration default :

include /etc/nginx/conf.d/ssl-params.inc;

Redémarrez nginx. Dans votre navigateur, rechargez la page.

Quelle est la réaction de votre navigateur ?

Rajoutez maintenant le scheme https devant l'URL.

Quelle est la réaction de votre navigateur ?

Acceptez d'ajouter l'exception dans votre navigateur.

Que veut dire le cadenas avec le point d'exclamation ?

Supprimez l'exception de sécurité de votre navigateur.

Remplacez votre certificat auto-signé par celui de l'autorité M1IF03-CAW : retournez dans le répertoire ssl, puis :

sudo cp ~/server.* .
sudo chmod 400 server.key

Redémarrez nginx et rechargez la page.

Quel est le nouveau message et que signifie-t-il ?

Ajoutez le certificat root situé ici dans votre navigateur (dans Firefox : menu Options / Vie privée et sécurité / Afficher les certificats / Importer).

fenêtre d'ajout de certificat de Firefox

Que se passe-t-il ?

Ajoutez maintenant une configuration pour rediriger automatiquement toutes les requêtes en HTTP vers HTTPS. Pour cela, modifiez le fichier default.conf (dans sites-available) :

Supprimez les directives listen 80 de la config actuelle

Rajoutez le bloc suivant :

server {
    listen 80;
    listen [::]:80;
    server_name _;
    return 308 https://$host$request_uri;
}

Redémarrez nginx et vérifiez que toutes les URIs sont correctement redirigées en HTTPS.

Quelle est la différence entre les codes de redirection 301 et 308 ?

3. Configuration d'un site Web

Dans cette partie, vous allez modifier le site existant et mettre en place votre propre site Web. Pour cela, identifiez le mécanisme qui permet de définir l'emplacement des différents sites hébergés par le serveur.

Pour conserver les conventions habituelles (héritées d'Apache), les différents sites ou parties de site que vous créerez dans cette partie seront placés dans le répertoire /var/www.
Conseil : changez l'utilisateur propriétaire de ce répertoire pour pouvoir éviter la commande sudo à chaque manipulation dessus...

Vous trouverez des astuces / patterns de configuration et les erreurs les plus souvent commises dans la configuration d'nginx sur cette page.

3.1. Configuration d'un site existant

Créez un sous-répertoire html de /var/www et changez le répertoire où sont stockés les fichiers du site par défaut pour ce sous-répertoire.
Indiquez le nom du fichier de configuration que vous avez modifié et le contenu que vous avez modifié.

Créez un sous-répertoire images de /var/www. À l'aide de la directive alias, modifiez le fichier de configuration du site default pour gérer les images de ce site dans ce répertoire. Pour cela, ajoutez-y une directive de bloc location pour mapper l'URL /images du site vers ce répertoire. Pour tester, vous pouvez utiliser la commande suivante pour placer un fichier dans le répertoire images :
wget perso.liris.cnrs.fr/lionel.medini/enseignement/logo_UCBL_transparent.gif. Modifiez ensuite le fichier index.html pour qu'il inclue l'image, de façon à avoir un résultat similaire à l'image ci-dessous.

première page nécessitant plusieurs requêtes avec nginx
Copiez-collez les modifications apportées au fichier de configuration dans la réponse au questionnaire.

3.2. Mise en place d'un nouveau site

Créez un site différent du site par défaut, que vous appelerez "monsite", qui répondra sur le port 8080 dont les données se trouveront dans un sous-répertoire de /var/www. Copiez-y la page d'accueil de votre site principal et modifiez un peu le texte pour pouvoir la reconnaître.

Indiquez la configuration que vous avez faite pour que "monsite" réponde et copiez-collez les parties significatives des fichiers créés ou modifiés.

Remarque : la configuration et l'activation des sites se fait à l'aide de liens symboliques (commande ln -s) entre des répertoires nommés sites-available et sites-enabled. Ce mode de configuration est un héritage de la configuration d'Apache. Ce fonctionnement n'est pas le même opur toutes les versions d'nginx. À vous de trouver le bon tuto...

3.3. Scripting côté serveur

Dans cette question, vous allez faire en sorte que monsite interprête les fichiers PHP, alors que le site principal sera utilisé pour servir les fichiers statiques.

Rajoutez dans monsite un fichier PHP simple (<?php phpinfo(); ?>) et requêtez-le avec votre navigateur. Comme PHP n'est pas installé sur le serveur, le fichier n'est pas interprêté.
Décrivez et expliquez - côté serveur et côté client - ce qui se passe et la raison pour laquelle vous obtenez ce comportement.
Aide : utilisez les outils de développement de votre navigateur pour voir les en-têtes HTTP.

Vous allez donc devoir installer un interprêteur PHP sur la machine et configurer nginx en conséquence. L'implémentation choisie est PHP-FPM (FastCGI process manager for PHP). La documentation officielle pour configurer nginx pour PHP-FPM est située ici. Toutefois, je vous conseille de suivre ce tutoriel pour installer le module php7-fpm.
Attention : PHP-FPM a besoin des droits en exécution sur les fichiers PHP. À vous d'ajouter ces droits sur aux utilisateurs du groupe www-data dans le répertoire correspondant.
Une fois la configuration réalisée, requêtez à nouveau votre fichier PHP pour vérifier que l'installation a réussi.
Copiez-collez la valeur du champ "System" affiché sur la page.

4. Front server / reverse proxy

Vous allez maintenant configurer votre site par défaut pour qu'il délègue les requêtes sur les fichiers PHP au site "monsite". Pour cela, utilisez la doc d'nginx située ici.

Pour tester, créez une première application Web comme suit 

Comparez les URI des liens générés par la page PHP selon qu'elle est requêtée à partir du site default ou de monsite. Que constatez-vous ?

Vous avez maintenant deux sites qui répondent sur des ports différents du serveur. Seul "monsite" permet d'interprêter du PHP, et le port 8080 sur lequel il répond est masqué au client par la directive qui met en oeuvre le reverse proxy. L'intérêt est de conserver un serveur en front qui se contentera de servir des requêtes simples et de déléguer les traitements plus complexes à d'autres serveurs (PHP, CGI, serveur Java, etc.).

5. Gestion des sessions

Vous allez modifier votre site PHP pour qu'il utilise la gestion de session PHP pour conserver des informations sur l'utilisateur (en l'occurrence, une chaîne de caractères représentant son pseudo).

Créez une page d'accueil en PHP qui :

Modifiez votre page PHP initiale (celle qui dit bonjour dans plusieurs langues) pour qu'elle commence par afficher le peudo de l'utilisateur, puis " vous dit : ", puis son affichage précédent
Par exemple : si mon pseudo est Lionel et si j'ai entré le prénom Toto et la langue anglaise dans le formulaire, je devrais obtenir : Lionel vous dit : Hello Toto

Testez le fonctionnement de votre application et vérifiez en particulier que vous pouvez envoyer plusieurs requêtes à partir de la page d'index et que le serveur se souvient de votre pseudo. Identifiez ensuite le mécanisme de gestion des sessions utilisé.

Quel est ce mécanisme ? Comment faire pour que le serveur vous "oublie" ?

Vérifiez en faisant la manipulation proposée et en observant les headers HTTP.

6. Répartition de la charge (load balancing)

Rajoutez à votre site dynamique une page PHP dans laquelle vous introduirez une latence qui mettra un peu de temps (5 secondes) à répondre. Dupliquez ensuite ce site, et faites en sorte que chaque instance affiche un numéro différent (pour pouvoir savoir celle qui répond) dans la réponse finale. Finalement, configurez le front nginx pour qu'nginx répartisse la charge en fonction du plus petit nombre de connexions de chacun des sites (voir la documentation)
Attention : la directive http est déjà dans le fichier nginx.conf qui inclut les fichiers de chacun de vos sites. Il ne faut donc pas la réécrire.

Requêtez plusieurs fois la page avec des clients / onglets différents pour vérifier le bon fonctionnement de la répartition. Incluez maintenant cette page contenant la boucle dans votre application qui dit bonjour (et dupliquez-la également, si ce n'est pas déjà fait). Testez-en le fonctionnement derrière le processus de load balancing.
Que se passe-t-il ? Pourquoi ?

Passez ensuite en mode de répartition par hash des adresse IP. Testez à nouveau.
Que se passe-t-il ? Comment vérifier tout de même que le load balancing fonctionne ?

7. Gestion du cache

Effacez le cache de votre navigateur, et via la console de développement, affichez les paramètres réseau.

Faites ensuite une requête vers l'un des fichiers HTML statiques de votre site default et observez les détails de la transaction HTTP dans la console.
Quel est le code de statut renvoyé ? Quels sont les headers de gestion du cache présents dans la réponse ?

Actualisez la page et observez à nouveau la transaction dans la console.
Quel est le code de statut renvoyé après actualisation ? Quels sont les headers de gestion du cache présents dans la requête et dans la réponse ?

Maintenant, éditez et modifiez la page sur le serveur et actualisez la page côté client.
Quel est le code de statut renvoyé après modification + actualisation ? Quels sont les headers de gestion du cache présents dans la requête et dans la réponse ?

Sur votre site dynamique (PHP), faites une requête d'envoi du formulaire et observez les headers HTTP.
Quels sont les headers de gestion du cache dans le cas d'une requête POST ?

Modifiez le comportement de gestion du cache concernant les pages statiques pour que le cache soit mis à jour toutes les minutes, et vérifiez le nouveau fonctionnement.
Quelle directive avez-vous utilisée ? Quels sont les headers de gestion du cache échangés ?

Revenez à l'état initial.

Creative Commons License
Valid XHTML 1.0 Transitional