Sommaire
Debian 9 64 bits – LXC
Introduction
Cet article a pour objectif de montrer quelques techniques (plus ou moins avancées) permettant une sécurisation complète d’un service web à travers l’installation d’un forum utilisant une base de données.
L’environnement utilisé sera un Debian 9 car c’est la dernière release de Debian à l’heure où j’écris l’article. Cependant les mêmes principes peuvent être appliqués à n’importe quelle distribution, et en plus de cela, vous serez en mesure de réutiliser les commandes que je fournis sur tous les dérivés de Debian (Ubuntu, Linux Mint, …).
Attention !!!!!
Sous VMware ne pas oublier d’autoriser le mode promiscuité dans les paramétrages réseaux
Installation et configuration des LXC
LXC, contraction de l’anglais Linux Containers est un système de virtualisation, utilisant l’isolation comme méthode de cloisonnement au niveau du système d’exploitation. Il est utilisé pour faire fonctionner des environnements Linux isolés les uns des autres dans des conteneurs partageant le même noyau et une plus ou moins grande partie du système hôte. Le conteneur apporte une limitation et une gestion de la priorisation de l’environnement d’exécution (processeur, mémoire vive, réseau, système de fichier…) et non pas de la machine. Pour cette raison, on parle de « conteneur » et non de machine virtuelle.
Préparation
Connectez vous via SSH en root sur votre machine.
Nous allons commencer par installer quelques dépendances :
Notez dans un coin les uid et gid des utilisateurs que vous venez de créer :
Les 2 fichiers sont très souvent identiques (si vous n’avez pas créé de groupes en fait), vous devez noter les ids en question, ici : 100000 (pour forum) et 165536 (pour bdd) qui est le début des ids qui leurs sont attribués. Si chez vous l’uid et le gid ne sont pas les mêmes, notez bien les 2 valeurs. Notez également le 65536 qui est le nombre d’ids attribués à un utilisateur.
Configuration
Création du bridge
Pour Bridge Natté
Pour Bridge sur le même réseau
Pour recharger la configuration du fichier interfaces, il suffit de relancer le service correspondant de cette manière :
service networking restart
En lancant la command ip a vous pouvez vérifier que le bridge a correctement été créé
Nous avons donc maintenant un genre de réseau interne qui est 192.168.1.0/24, celui ci sera le réseau utilisé par nos LXC.
Sur notre serveur, l’interface qui donne sur le net est eno1 (vous aurez peut-être un nom différent tel que eth0). Afin de donner un accès internet aux machines de notre réseau interne, il faut créer une règle masquerade qui va permettre à notre réseau interne de communiquer via l’interface qui donne sur le net. Ceci peut-être réalisé à l’aide de la commande suivante (pensez à remplacer l’interface eno1 par la votre) :
Configuration des LXC
Afin d’autoriser les LXC à créer des interfaces sur la machine, créez le fichier /etc/lxc/lxc-usernet et ajoutez dedans :
Nous allons devoir créer un fichier de configuration par defaut qui sera utilisé lors de la création des containers. Ce fichier spécifiera entre autre les uid et gid à utiliser, ainsi que la configuration réseau.
Commencez par executer ces commandes :
Créez maintenant .config/lxc/default.conf avec votre editeur préféré (vim, nano, …) et mettez y :
Pensez bien à utiliser les ids notés précédement ! Pour l’utilisateur forum nous avions noté 100000.
On utilise l’adresse IP 192.168.1.2 car 192.168.1.1 est l’adresse utilisée par le bridge, c’est notre gateway.
Faites un exit pour retourner sur le compte root et répétez l’opération pour l’utilisateur bdd (depuis le su -l) et donc en remplacant 100000 par 165536. Pensez également à utiliser une adresse IP differente, donc 192.168.1.3 en toute logique.
Creation du container
- lxc-create -t download -n forum_container
Un assistant d’installation va se lancer afin que vous puissiez choisir quelle distribution utiliser, quelle version, et quelle architecture utiliser.
Si comme moi vous souhaitez un Debian 9 64bits, je vous invite à utiliser cette commande à la place :
- lxc-create -t download -n forum_container — -d debian -r stretch -a amd64
Après un court instant, le container devrait être créé.
Utilisation du container
- lxc-start -n forum_container -o /tmp/logs -l DEBUG
Les paramètres -o et -l permettent de logger la sortie du lxc-start afin de résoudre un potentiel problème qui pourrait empêcher le démarrage du container. Donc si votre container ne se lance pas, allez voir dans le fichier /tmp/logs.
Si tout s’est bien passé, vous ne devriez avoir aucune sortie, comme si rien ne s’était passé.
Il vous suffit ensuite de rejoindre ce container à l’aide de la commande suivante :
- lxc-attach -n forum_container –clear-env
Afin de vérifier que vous avez bien un accès à internet, mettez à jour les repos :
- apt update
Vous n’avez pas d’autre moyen de tester votre accès internet car les utilitaires classiques tels que ping, wget, ou encore curl, ne sont pas installés par défaut. Si vous n’avez toujours pas internet, retournez en arrière et verifiez que vous avez correctement tout configuré.
- export PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin
Vous devriez maintenant être en mesure d’installer n’importe quel programme à l’interieur de votre container, testez donc d’installer l’utilitaire ping :
- apt install inetutils-ping
- root@forum_container:/# ping 192.168.1.3
- PING 192.168.1.3 (192.168.1.3): 56 data bytes
- 64 bytes from 192.168.1.3: icmp_seq=0 ttl=64 time=0.075 ms
- 64 bytes from 192.168.1.3: icmp_seq=1 ttl=64 time=0.070 ms
- 64 bytes from 192.168.1.3: icmp_seq=2 ttl=64 time=0.346 ms
Mise en place d’un reverse proxy
Dans ce chapitre, nous allons mettre en place un reverse proxy sur le système hote. Celui-ci sera chargé de chiffrer les communications avec le navigateur des clients et de rediriger les requetes sur le service approprié.
Si par exemple un client se connecte sur notre serveur en ayant rentré dans son navigateur forum.domaine.fr, il faudra transférer les reqûetes à notre LXC forum_container. On pourrait très bien imaginer que d’autres services tournent sur notre serveur, le job du reverse proxy sera donc de créer une correspondance entre un sous-domaine et un LXC.
Préparation
Commencez par installer nginx sur le serveur hote (pas dans un LXC donc) en root :
- apt install nginx
Configuration
Dans cette partie, je vous propose une configuration simple mais efficace pour rediriger un domaine ou sous-domaine au LXC correspondant.
Remplacez le contenu de votre /etc/nginx/nginx.conf par le suivant :
- user www-data;
- worker_processes auto;
- pid /run/nginx.pid;
- include /etc/nginx/modules-enabled/*.conf;
- events {
- worker_connections 768;
- # multi_accept on;
- }
- http {
- ##
- # Configuration de base
- ##
- sendfile on;
- tcp_nopush on;
- tcp_nodelay on;
- keepalive_timeout 65;
- types_hash_max_size 2048;
- server_name_in_redirect on;
- include /etc/nginx/mime.types;
- default_type application/octet-stream;
- ##
- # Configuration SSL
- ##
- #ssl_certificate /path_to/fullchain.pem;
- #ssl_certificate_key /path_to/privkey.pem;
- #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
- #ssl_prefer_server_ciphers on;
- #ssl_dhparam /path_to/dhparams.pem;
- ##
- # Configuration des logs
- ##
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log;
- ##
- # Gzip Settings
- ##
- gzip off; # Ne surtout pas mettre à on -> BREACH vuln
- gzip_disable « msie6 »;
- # gzip_vary on;
- # gzip_proxied any;
- # gzip_comp_level 6;
- # gzip_buffers 16 8k;
- # gzip_http_version 1.1;
- # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
- ##
- # Virtual Host Configs
- ##
- include /etc/nginx/conf.d/*.conf;
- include /etc/nginx/sites-enabled/*;
- #Redirect http –> https
- # server {
- # listen 80;
- # server_name domaine.fr *.domaine.fr;
- # return 301 https://$host$request_uri;
- # }
- server {
- # listen 443;
- # ssl on;
- listen 80;
- server_name domaine.fr www.domaine.fr forum.domaine.fr;
- add_header Strict-Transport-Security « max-age=31536000 »;
- add_header X-XSS-Protection « 1; mode=block »;
- add_header X-Content-Type-Options nosniff;
- location / {
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_pass http://192.168.1.2;
- }
- # Pour Certbot, si vous voulez utiliser des certificats Let’s Encrypt
- location /.well-known {
- root /var/www/html;
- }
- }
- # Vous pouvez ajouter d’autres machines très simplement !
- # server {
- # listen 443;
- # ssl on;
- # add_header Strict-Transport-Security « max-age=31536000 »;
- # add_header X-XSS-Protection « 1; mode=block »;
- # add_header X-Content-Type-Options nosniff;
- # server_name wiki.domaine.fr;
- # location / {
- # proxy_set_header Host $host;
- # proxy_set_header X-Real-IP $remote_addr;
- # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- # proxy_set_header X-Forwarded-Proto $scheme;
- # proxy_pass http://192.168.1.X;
- # }
- # location /.well-known {
- # root /var/www/html;
- # }
- # }
- }
Pensez bien sûr à remplacer tous les domaine.fr par votre nom à vous puis redémarrez ensuite NGINX :
- service nginx restart
HTTPS
Création des certificats
Cette partie est facultative si vous possédez déjà vos propres certificats, nous allons ici utiliser Let’s Encrypt qui nous permet d’obtenir des certificats gratuitement !
Afin de mettre en place ces certificats, nous allons utiliser Certbot qui est un utilitaire qui va générer les certificats.
Commencez par installer celui-ci :
- apt install certbot
Puis générez les certifs :
- certbot certonly –webroot -w /var/www/html -d domaine.fr -d www.domaine.fr -d forum.domaine.fr
Regardez dans le dossier /etc/letsencrypt/live, vous devriez avoir un dossier portant le nom de votre domaine.
Nous allons maintenant générer un certificat Diffie Hellman pour l’échange de clés :
- openssl dhparam -out /etc/letsencrypt/live/domaine.fr/dhparams.pem 2048
Je considère que générer une clé de 2048 bits est le minimum vu la puissance de calcul des ordinateurs actuels. Mais si vous avez du temps OU une machine très performante, je vous invite à faire une clé de 4096 bits à la place.
Renouvellement des certificats
Cette partie concerne encore une fois uniquement les certificats Let’s Encrypt.
Testez que la regénération des certificats est bien fonctionnelle à l’aide de la commande :
- certbot renew –dry-run
Si tout s’est bien passé, vous pouvez continuer en créant un cron à l’aide de la commande suivante :
- crontab -e
Choisissez votre éditeur de texte préféré et ajoutez dans le fichier en édition la ligne suivante :
- 30 4 1 * * root certbot renew
Tous les 1er du mois à 4h30, la commande certbot renew va être lancée et va regénérer les certificats.
Utilisation
Nous allons dans cette partie modifier légerement la configuration de notre reverse proxy NGINX afin de lui faire utiliser nos certificats.
Editez le fichier /etc/nginx/nginx.conf et modifiez les éléments suivants :
Décommentez toute la configuration de SSL :
- ssl_certificate /path_to/fullchain.pem;
- ssl_certificate_key /path_to/privkey.pem;
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
- ssl_prefer_server_ciphers on;
- ssl_dhparam /path_to/dhparams.pem;
Et remplacez path_to par le chemin d’accès vers vos certifs. Pour Let’s Encrypt c’est très probablement dans /etc/letsencrypt/live/domaine.fr.
Si vous vous demandez pourquoi SSLv3 doit être désactivé, rendez-vous ici (lecture en anglais).
Décommentez ensuite les choses suivantes :
- server {
- listen 80;
- server_name domaine.fr *.domaine.fr;
- return 301 https://$host$request_uri;
- }
Ceci permet de forcer le passage de http à https à tous les utilisateurs.
Pour finir, dans le bloc server qui se charge de faire la redirection vers 192.168.1.2, utilisez le port 443 au lieu du port 80 et activez SSL :
- listen 443;
- ssl on;
- #listen 80;
Vous pouvez maintenant redémarrer NGINX, tout devrait fonctionner :
- service nginx restart
Installation et configuration de la base de données
Préparation
Commencez par rejoindre le LXC de votre utilisateur bdd et redéfinissez le PATH comme vu précédement.
Installez en suite MariaDB (ou autre SGBD) :
- apt install mariadb-server mariadb-client
Lancez ensuite la commande suivante :
- mysql_secure_installation
Définissez un mot de passe pour le compte root de la base de données et dites oui (Y) tout au long du script.
Création
Nous allons commencer par nous connecter en local au SGBD à l’aide de la commande suivante :
- mysql -u root
Une fois connecté, nous allons créer une base de données qui ne sera utilisée que pour le service web correspondant, à savoir : le forum. Lancez donc la commande suivante afin de créer cette base de données :
- MariaDB [(none)]> CREATE DATABASE mybb_db;
- Query OK, 1 row affected (0.00 sec)
Créez ensuite un utilisateur :
- CREATE USER ‘mybb_db’@‘192.168.1.2’ IDENTIFIED BY ‘password’;
Comme vous pouvez le constater, on a créé un utilisateur nommé mybb_db. Cet utilisateur sera en mesure d’être utilisé uniquement depuis l’adresse IP 192.168.1.2 qui est en fait l’adresse IP du forum_container.
Nous devons ensuite donner les droits à cet utilisateur pour qu’il puisse utiliser la base de données précédement créée :
- GRANT ALL PRIVILEGES ON mybb_db.* to ‘mybb_db’@‘192.168.1.2’;
Afin d’autoriser les connexions distantes (au sein du réseau local) au SGBD, modifiez le fichier /etc/mysql/mariadb.conf.d/50-server.cnf et plus précisément :
- bind-address = 192.168.1.3
Redémarrez mariadb :
- systemctl restart mariadb
Voilà qui est terminé pour la création de la base de données. Il est très fortement recommandé de bien cloisonner les différents utilisateurs et les accès qui leurs sont accordés sur la bdd afin d’éviter qu’un service qui a été piraté soit en mesure d’altérer la base de données d’un autre service.
Installation et configuration du serveur web
Préparation
- apt install nginx php-fpm php-mysql wget unzip
- server {
- listen 80 default_server;
- listen [::]:80 default_server;
- root /var/www/html;
- index index.php;
- server_name www.domaine.fr domaine.fr forum.domaine.fr;
- location / {
- try_files $uri $uri/ /index.php?$args;
- }
- location = /favicon.ico {
- log_not_found off;
- access_log off;
- }
- location = /robots.txt {
- allow all;
- log_not_found off;
- access_log off;
- }
- error_page 404 /404.html;
- location ~ \.php$ {
- try_files $uri =404;
- fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
- fastcgi_index index.php;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- include fastcgi_params;
- fastcgi_param REMOTE_ADDR $http_x_real_ip; # Permet d’utiliser la véritable IP du visiteur et non pas celle du reverse proxy
- }
- }
- systemctl restart nginx
Installation d’un CMS
- cd /tmp && wget https://resources.mybb.com/downloads/mybb_1812.zip
- unzip mybb_1812.zip
- mv Upload/* /var/www/html/
- chown -R www-data:www-data /var/www/html/
Commentaires récents