Memcached, la mémoire des serveurs web
I. Présentation
Dans le contexte des serveurs web tels qu’Apache ou même Nginx, on recherche généralement à sécuriser et à rendre celui-ci plus résilient. En matière de sécurité, on pense immédiatement à OpenSSL et aux certificats permettant d’effectuer des requêtes HTTPS. Mais, en ce qui concerne l’autre aspect, on peut avoir recours à différents processus de mise en cache permettant d’alléger la charge du serveur web.
A cet égard, memcached est un système de cache distribué "in-memory" de très haut niveau notamment utilisé pour accroître la vitesse de réponse des sites web possédant des bases de données quelque peu chargées. En effet, alors que les sites web grandissent et voient leur trafic réseau devenir de plus en plus important, l’une des préoccupations principale d’un administrateur va être de s’intéresser à la charge du serveur web en production.
Ceci est surtout vérifié pour des bases de données non distribuées où l’accroissement de transactions grandissantes va apporter également un accroissement assez conséquent du trafic et de la charge. Un des moyens efficace de lutter contre cette surcharge est d’activer un mécanisme de gestion de cache objet en mémoire, tel que memcached. L’outil favorise aussi le stockage d’objets de n’importe quelle nature. Généralement, chaque CMS qui se respecte dispose d’un plugin ou d’un module additionnel permettant de valoriser memcached. Par ailleurs, de nombreux langages de programmation disposent également d’une bibliothèque memcached. Cela inclut :
- PHP
- Perl
- Python
- Ruby
REMARQUE : du fait de sa fonctionnalité d’exécution en mémoire, l‘outil memcached est réellement plus rapide car il ne nécessite aucune opération d’écriture sur disque.
Dans ce tutoriel, je vous propose de mettre en œuvre un memcached sur une distribution CentOS7 pour un serveur web Apache en isolé. Mais, la démarche s’applique parfaitement à des fermes de serveurs plus importantes (ce qui est généralement le cas en entreprise et en production). Nous verrons également l’ensemble des modules que l’on peut aisément ajouter à l’outil pour permettre un meilleure interfaçage avec les différents langages de programmation et autres CGI liés aux serveurs web.
II. Installation de memcached
Généralement, avant d’installer une nouvelle fonctionnalité, on commence par mettre à jour l’ensemble des packages déjà installés et configurés sur le système :
# yum –y update
On peut alors ajouter notre nouvel outil memcached en exécutant l’instruction suivante :
# yum –y install memcached
REMARQUE : si l’on omet l’option –y il faudra alors répondre aux différentes questions que l’utilitaire pourra proposer :
Par défaut, lors de son installation, memcached démarre sur le port TCP/11211. En tout cas, c’est ce qui est mémorisé dans le fichier de configuration memcached se trouvant dans le répertoire /etc/sysconfig. Libre à chacun d’entre vous de configurer votre propre port d’écoute du service. Les principaux paramètres à modifier sont les suivants :
PORT="11211" USER="memcached" MAXCONN="1024" CACHESIZE="64" OPTIONS=""
Parmi les options intéressantes, étant donné que le protocole UDP est plus susceptible d’être piraté au travers de déni de service que TCP, on peut le désactiver en ajoutant –U 0 dans le champ OPTIONS :
OPTIONS="-l 127.0.0.1 –U 0"
Une autre option concerne plus spécifiquement la sécurité. On peut déclarer un utilisateur authentifié grâce à l’utilisation du protocole SASL. Pour se faire, il suffit également d’ajouter l’option –S :
OPTIONS="-l 127.0.0.1 –U 0 -S"
ATTENTION : l’ajout de cette dernière option nécessite l’installation des packages de bibliothèque SASL suivants :
# yum –y install cyrus-sasl-devel cyrus-sasl-plain
On peut ensuite configurer cette nouvelle fonctionnalité en créant un répertoire /etc/sasl, dédié à SASL afin d’y placer un fichier de configuration memcached.conf propre à memcached dans lequel on ajoutera les lignes suivantes :
mech_list: plain log_level: 5 sasldb_path: /etc/sasl/memcached-sasldb
Bon, on peut alors créer la base SASL avec nos paramètres de credentials et lui octroyer les droits de propriété de l’utilisateur memcached:
# saslpasswd2 –a memcached –c –f /etc/sasl/memcached-sasldb phil # chown memcached:memcached /etc/sasl/memcached-sasl # systemctl restart memcached
On peut évidemment changer le nom de l’utilisateur par défaut lié au service memcached ou encore le nombre de connexions autorisées grâce au paramètre MAXCONN ou la taille du cache en mégabytes au travers du paramètre CACHESIZE. Dès que votre paramétrage est complet on peut alors redémarrer le service :
# systemctl restart memcached # systemctl enable memcached
IMPORTANT : dans le cas où l’on a activé la fonctionnalité SASL, pour pouvoir se connecter à la base d’authentification, il suffit d’exécuter l’ordre suivant :
# memstat --servers="127.0.0.1" --username=phil --password=*******
Ensuite, il faut également s’assurer que l’on dispose bien d’un serveur Apache en exécutant l’instruction ci-dessous :
# systemctl status httpd
On devrait alors voir s’afficher les caractéristiques du service httpd suivantes :
On peut alors passer à l’installation des différents composants propre aux langages de programmation en fonction sur le serveur web. Pour l’exercice on effectuera l’installation du module concernant PHP :
# yum –y install php-pecl-memcached
RAPPEL : le répertoire par défaut du serveur web est /var/www/html, dans lequel on peut alors placer un fichier témoin info.php contenant le code suivant :
< ?php phpinfo() ; ?>
On devrait alors, preuve ultime de bon fonctionnement, pouvoir lister les caractéristiques de la rubrique memcached qui s’affiche à l’écran :
Ou, il est aussi possible d’interroger le langage directement avec l’instruction suivante :
# php –r "phpinfo() ;"|grep memcache
Ceci devrait alors faire afficher l’ensemble de lignes décrites dans la capture suivante, montrant clairement que l’utilitaire memcached a bien été intégré :
On peut ensuite vérifier que le daemon memcached est bien activé en exécutant la commande suivante :
# ps aux | grep memcached
On devrait alors visualiser les caractéristiques intrinsèques du service :
On peut également interroger le système afin de vérifier que le port TCP/11211 est bien à l’écoute du service memcached. Enfin, test ultime, il est possible de créer un script tst-memcached.php, que l’on placera dans le répertoire /var/www/html et dans lequel on va ajouter ces lignes :
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); $result = $mem->get("hey"); if ($result) { echo $result; } else { echo "Pas de clé trouvée. J'en ajoute une!"; $mem->set("Hey", "New record in memcached!") or die("Enregistrement impossible !!"); } ?>
Si le service est correctement démarré et configuré, on devrait recevoir la réponse suivante. Dans le cas contraire on aura le message stipulant que le service memcached ne peut pas enregistrer de nouvelles valeurs :
Ce qui est remarquable, c’est que cela peut aussi s’appliquer à des enregistrements en bases de données MySQL, par exemple. Considérons que l’on dispose d’une chaine de connexion ‘toto/******’ à la base de donnée tst_memory, dans le script PHP précédent, on devra remplacer les lignes de test ‘if else’ par les lignes ci-dessous :
mysql_connect( "127.0.0.1", "toto", "******") or die(mysql_error()) ; mysql_select_db("tst_memory") or die(mysql_error()) ;
Dans la continuité de cette démarche, on peut alors ajouter de nouveaux enregistrements en base de données en ajoutant les lignes ci-dessous au script initial :
$query = "SELECT name FROM myTable WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey);
Afin d’être certain que ce nouvel enregistrement sera bien pris en considération et intégré à la base de données, on peut ajouter les deux lignes suivantes :
if ($result) { print "<p>Data was: " . $result[0] . "</p>"; print "<p>Phase de cache réussie!</p><p>Record enregistré dans memcached!</p>"; }
III. Configuration des pare-feu
Maintenant que l’on aperçoit le moyen efficace et rapide de stocker des informations en mémoire, sans nécessairement utiliser de disque intermédiaire, il est temps de s’intéresser à la technique de déclaration des ports de communication de memcached au sein du pare-feu iptables. L’idée est d’autoriser le port TCP/11211 pour les adresses autorisées à utiliser le service, en déclarant les instructions suivantes :
# iptables –A INPUT –p tcp –dport 11211 –m state --state NEW –m iprange --src-range 192.168.1.1-192.168.1.15 –j ACCEPT
On peut alors redémarrer le service iptables :
# systemctl restart iptables
Bien évidemment, si en lieu et place de l’utilitaire iptables on a activé firewall-cmd, il faudra alors déclarer les lignes suivantes :
# firewall-cmd --permanent --new-zone=memcached # firewall-cmd --permanent --zone=memcached --add-port=11211/tcp # firewall-cmd --permanent --zone=memcached --add-source=192.168.1.1-192.168.1.15
IV. Conclusion
Avec ce genre d'outil, on peut véritablement alléger la charge de nos serveurs web et surtout sécuriser les échanges via des mécanismes de type SASL. Ajoutons que ce type de mécanisme peut être adapté à des framework comme Django, Drupal ou encore Rails au travers du langage Ruby. Il existe même un container Docker permettant d’initialiser un cache memcached. L’utilisation de ce dernier est toutefois à utiliser avec précaution car certaines attaques de type DDoS peuvent être menées contre ce service, par manque de sécurité. Il est donc plus que conseillé de bien désactiver le protocole UDP et d’utiliser un mode d’authentification tel que SASL.