Construire un serveur web NodeJS avec HAProxy et Let’s Encrypt sur Debian Stretch

Dans ce guide, je vais vous montrer comment configurer un serveur NodeJS en utilisant HAProxy et Let’s Encrypt sur Debian Stretch. Vous apprendrez également comment transformer votre application NodeJS en démon afin qu’elle puisse être arrêtée, démarrée et redémarrée et redémarrer automatiquement lors du crash / redémarrage.

Dans ma configuration HAProxy agit comme un proxy inverse, les demandes de mandatement du port 443au port de l’application NodeJS (dans ce tutoriel , nous courons 3 instances de l’application sur les ports 500150025003) et utiliser HAProxy pour équilibrer la charge entre eux. J’aurais pu utiliser le cluster Nodes pour faire cela, mais HAProxy est plus simple, et offre plus de fonctionnalités. A mon avis, il est beaucoup plus facile de mettre à l’échelle une application qui utilise déjà HAProxy plutôt que d’avoir à refactoriser l’installation par la suite.

Nous allons également sécuriser notre application en utilisant HTTPS et Let’s Encrypt et entrer dans un petit détail sur la sécurisation du pare-feu.

C’est un article assez long alors allez prendre un café, ou une bière, et commençons.

Conditions préalables

Avant de commencer, vous aurez besoin de quelques petites choses:

  • Debian 9 (Stretch) est nécessaire pour suivre ce guide.
  • Un nom de domaine configuré pour pointer vers votre serveur. Ceci est requis pour LetsEncrypt. Sans cela, vous ne pourrez pas utiliser HTTPS.

Je recommande également l’utilisation de quelques mesures de sécurité de base:

  • Créer un nouvel utilisateur Ne pas utiliser root!
  • Désactiver la connexion SSH avec mot de passe. Utilisez la cryptographie à clé publique.
  • Désactiver la rootconnexion SSH
  • Mettre en place un pare-feu sécurisé pour exposer uniquement les ports requis et bloquer tout le reste (j’en discute à la fin de l’article)

Prêt à commencer? Allons-y!

Installer les paquets requis

J’utilise une installation Debian minimale qui n’inclut pas les programmes tels que gitou curl. Nous en aurons besoin. Permet de les installer d’abord:

sudo apt-get update
sudo apt-get install -y curl \
    git \
    build-essential \
    iptables-persistent
  • curl: Obligatoire pour installer NodeJS
  • git: Obligatoire pour déployer l’application sur le serveur
  • build-essential: Obligatoire pour installer certains paquets Node
  • iptables-persistent: Sauvegarde permanente des règles iptables

Remarque: Lors de l’installation iptables-persistent, une boîte de dialogue vous demande si vous souhaitez enregistrer les règles iptables en cours. Si vous configurez cela sur un nouveau serveur, sélectionnez les <no>deux questions.

Installation de NodeJS

Maintenant que nous avons curl installé, nous pouvons installer NodeJS. Dans ce guide, j’utiliserai NodeJS 8. Actuellement, le statut LTS de la version 8 est toujours en attente. Si cela est important, envisagez d’installer une version LTS.

Exécutez les commandes suivantes pour installer Node 8:

sudo curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

Si tout fonctionne correctement, NodeJS va maintenant être installé.

Installez l’application Web de test

J’ai créé une application de test avec NodeJS spécifiquement pour cet article. C’est un script très simple qui crée 3 http.createServer instances.

Jetez un oeil à la source: https://github.com/JamesTheHacker/nodebox-testapp

Important: passez web.webà votre utilisateur et groupe, avant d’exécuter la commande suivante. Si vous ne le faites pas, vous n’aurez pas les permissions pour écrire des fichiers /var/www.

sudo mkdir /var/www
sudo chown -R web:web /var/www
cd /var/www
git clone https://github.com/JamesTheHacker/nodebox-testapp .

Chiffrons les certificats SSL / TLS pour SSH

Il est temps de générer un certificat SSL / TLS Let’s Encrypt pour configurer HTTPS. Pour ce faire, nous allons utiliser certbot. Cela générera les certificats requis pour configurer notre application avec haproxy pour utiliser HTTPS au lieu du HTTP non sécurisé. Google a un document fantastique sur la raison pour laquelle vous devriez utiliser HTTPS.

Depuis le site de Certbot :

Certbot a été développé par EFF et d’autres en tant que client pour Let’s Encrypt . Certbot fait partie des efforts déployés par EFF pour chiffrer l’ensemble de l’Internet. Les sites Web doivent utiliser HTTPS pour sécuriser le Web. Avec HTTPS Everywhere, Certbot vise à construire un réseau plus structurellement privé, sûr et protégé contre la censure.

Installez Certbot :

sudo apt-get installer -y certbot

Nous devons maintenant valider le domaine et obtenir un certificat. Nous utiliserons le --manual plugin de Certbot et dnsprouverons que nous contrôlons notre domaine.

sudo certbot certonly --manual --preferred-défis dns---email votre email -d www.your-domain.com -d your-domain.com

Vous devrez changer les éléments suivants:

  • your-email: Définissez ceci sur votre adresse e-mail
  • your-domain.com: Définissez ceci sur votre nom de domaine
  • www.yourdomain.com: Réglez ceci sur votre nom de domaine inc. lawww

TRÈS IMPORTANT! Avant d’exécuter la commande suivante, assurez-vous d’avoir un A enregistrement pour your-domain.com et www.your-domain.com.

C’est facile si vous utilisez Digital Ocean: voir ici .

Suivez les instructions à l’écran. Lorsqu’on vous demande « Êtes-vous d’accord avec votre adresse IP ?», Appuyez sur Y(si vous n’êtes pas satisfait de cela, vous devrez consulter le manuel de Certbot pour d’autres méthodes de validation).

Au cours de l’installation, il vous sera demandé d’ajouter 2 TXTenregistrements à votre nom de domaine avec des instructions sur ce qu’il faut ajouter (sur les TXTenregistrements Digital Ocean peuvent être ajoutés dans le panneau de contrôle). Après avoir ajouté les TXTenregistrements, laissez leur temps de propagation, sinon Certbot échouera et vous devrez répéter le processus. Quelques minutes suffisent habituellement.

Voici un exemple de configuration et le message de félicitations en cas de succès:

 

Certificats de renouvellement automatique

Les certificats Let’s Encrypt sont valides pendant 90 jours, après quoi ils expirent. Lorsqu’ils expirent, ils doivent être renouvelés afin d’obtenir un nouveau certificat.

Pour garantir que les certificats restent valides et à jour, sans temps d’arrêt, nous créerons un cronjob qui certbot renewpermettra de renouveler les certificats non valides. Si un certificat doit expirer dans les 30 jours, il certbotsera mis à jour.

Ouvrez le crontab:

sudo crontab -e

Ajoutez la ligne suivante:

00 01,13 * * * root / usr / local / bin / certbot renouveler --post-hook "service haproxy restart" --quiet

Cela crée un cronjob qui s’exécute deux fois par jour pour vérifier (à 1h et 13h) la validité du certificat. S’il est proche d’expirer, il sera automatiquement renouvelé. L’ --post-hookargument redémarrera haproxy pour que le nouveau certificat prenne effet.

Lecture recommandée:

Installation et configuration de HAProxy

Nous utiliserons HAProxy comme proxy inverse / équilibreur de charge. Au lieu d’équilibrer la charge des applications sur différents serveurs, nous équilibrerons les applications sur différents ports. Il est vraiment facile de configurer l’équilibrage de la charge de différents serveurs si nécessaire.

Installez HAProxy :

sudo apt-get installer -y haproxy

Avant de configurer HAProxy, nous avons décidé de combiner la chaîne complète et la clé privée créées dans la section précédente, et de les copier /etc/haproxy/certs. N’oubliez pas de changer your_domain.comde nom de domaine:

sudo mkdir -p /etc/haproxy/certs 
sudo sh -c 'cat /etc/letsencrypt/live/www.your_domain.com/fullchain.pem /etc/letsencrypt/live/www.votre_domaine.com/privkey.pem > /etc/haproxy/certs/your_domain.com.pem

Il est maintenant temps de créer le fichier de configuration HAP Roxy. En utilisant votre éditeur de texte favori, ouvrez /etc/haproxy/haproxy.cfg. Copiez et collez le fichier de configuration ci-dessous et remplacez toutes les instances de your_domain.comvotre domaine et toutes les instances de public_idl’adresse IP publique du serveur:

Remarque:  J’ai mis le haproxy.cfg modèle sur GitHub, si vous souhaitez l’utiliser à la place : ICI

    journal global / dev / log local0 
    log / dev / log local1 notice 
    chroot / var / lib / haproxy 
    stats socket /run/haproxy/admin.socket mode 660 niveau admin 
    stats timeout 30s 
    utilisateur haproxy 
    groupe haproxy 
    démon 
    maxconn 2048 
    tune.ssl.default -dh-param 2048
par défaut 
    journal 
    mode global 
    option http httplog 
    option dontlognull 
    option option forwardfor 
    http-server-close
frontend www-http 
    lier public_ip : 80 
    reqadd X-Forwarded-Proto: \ http 
    default_backend www-backend
frontend www-https 
    lier public_ip : 443 crs ssl / etc / haproxy / certs / votre_domaine .pem 
    reqadd X-Forwarded-proto: \ https 
    acl letsencrypt-acl chemin_beg /.well-known/acme-challenge/ 
    use_backend letsencrypt-backend si letsencrypt -acl 
    default_backend www-backend
backend www-backend 
    schéma de redirection https if! {ssl_fc} 
    mode http 
    balance roundrobin 
    type de table-stick taille ip 200k expire 100m 
    stick sur 
    serveur src www-1 127.0.0.1:5001 
    serveur de vérification www-2 127.0.0.1:5002 
    serveur de vérification www -3 127.0.0.1:5003 vérifier
backend letsencrypt-backend
   server letsencrypt 127.0.0.1:54321

Redémarrer haproxy :

service sudo redémarrage haproxy

Lecture recommandée:

Démoniser l’application Web avec Systemd

Systemd est un gestionnaire de système et de service pour Linux. Nous allonsutiliser pour transformer notre application NodeJS en un démon qui nous permet destop,startetreloadl’application. Il démarre également automatiquement une application NodeJS lorsque le serveur se bloque ou redémarre.

Pour transformer une application en démon, nous devons créer un nouveau fichier unité Systemd . C’est simplement un fichier qui contient des directives de configuration qui décrivent et définissent le comportement de notre démon.

En utilisant votre éditeur de texte favori, ouvrez le fichier /etc/systemd/system/nodeapp.service et copiez les directives de configuration suivantes:

[Unité] 
Description = Application Web NodeJS 
Après = network.target
[Service] 
ExecStart = / usr / bin / node / 
var /www/server.js ExecReload = / bin / kill -HUP $ MAINPID 
Restart = toujours 
StandardOutput = syslog 
StandardError = syslog 
SyslogIdentifier = nodeapp 
Utilisateur = web 
Groupe = web 
Environnement = PATH = / usr / bin: / usr / local / bin 
Environnement = NODE_ENV = production 
WorkingDirectory = / var / www /
[Installer] 
WantedBy = multi-user.target

Sur mes systèmes je cours mes applications en utilisant un utilisateur non privilégié habituellement appelé web. Vous utilisez probablement un nom d’utilisateur différent. Changez User=webet Group=webau besoin. N’UTILISEZ JAMAIS DE RACINE! TU AS ÉTÉ PRÉVENU!

Une fois que vous avez créé et modifié le fichier, exécutez les commandes suivantes pour que les modifications prennent effet:

sudo systemctl active nodeapp 
sudo systemctl start nodeapp

Les commandes suivantes peuvent être utilisées pour startstopet reloadl’application:

sudo systemctl démarrer nodeapp 
sudo systemctl arrêter nodeapp 
sudo systemctl recharger nodeapp

… et utilisez journalctlpour afficher les journaux d’application:

sudo journalctl -u nodeapp

Si vous êtes nouveau sur systemd, je vous recommande fortement de lire ceci: https://medium.com/@johannes_gehrs/getting-started-with-systemd-on-debian-jessie-e024758ca63d

Tester tout fonctionne

Avant de configurer le test de pare-feu que tout fonctionne en visitant votre site Web dans le navigateur. Si tout s’est bien passé, vous devriez voir une page similaire à celle ci-dessous.

Aussi, redémarrez votre serveur et visitez l’URL … ça marche toujours.

Configurer un pare-feu sécurisé

Nous avons presque terminé, je le promets. La dernière partie du guide consiste à configurer un pare-feu sécurisé. J’utilise une approche tout en bloc où je bloque tout et n’ouvre que les ports nécessaires. C’est le moyen le plus sûr d’installer un pare-feu.

Les règles suivantes supposent que votre serveur Web nécessite l’ouverture des ports suivants (n’hésitez pas à les modifier):

  • Port 22: requis pour SSH
  • Port 53: requis pour DNS
  • Port 80: Ceci est utilisé pour HTTP. Bien que nous utilisions HTTPS, il est important de laisser ce port ouvert. Si quelqu’un accède à votre site Web en utilisant HTTP, il sera automatiquement mis à jour vers HTTPS.
  • Port 443: requis pour HTTPS

Copiez les commandes ci-dessous dans un nouveau fichier appelé firewall-setup.sh:

#! / bin / bash
iptables -t filtre -F 
iptables -t filtre -X
iptables -t filtre -P INPUT DROP 
iptables -t filtre -P FORWARD DROP 
iptables -t filtre -P OUTPUT DROP
iptables -A INPUT -m état --state RELATED, ESTABLISHED -j ACCEPT 
iptables -A état OUTPUT -m - state RELATED, ESTABLISHED -j ACCEPT 
iptables -t filtre -A INPUT -i lo -j ACCEPT 
iptables -t filtre - A OUTPUT -o lo -j ACCEPT
iptables -t filtre -A OUTPUT -p tcp --dport 53 -j ACCEPT 
iptables -t filtre -A OUTPUT -p udp --dport 53 -j ACCEPT 
iptables -t filtre -A INPUT -p tcp --dport 53 -j ACCEPTER 
iptables -t filtre -A INPUT -p udp --dport 53 -j ACCEPTER
iptables -t filtre -A INPUT -p tcp --dport 22 -j ACCEPT 
iptables -t filtre -A OUTPUT -p tcp --dport 22 -j ACCEPTE
iptables -t filtre -A OUTPUT -p tcp --dport 80 -j ACCEPT 
iptables -t filtre -A INPUT -p tcp --dport 80 -j ACCEPTE
iptables -t filtre -A OUTPUT -p tcp --dépôt 443 -j ACCEPT 
iptables -t filtre -A INPUT -p tcp --dépôt 443 -j ACCEPTE

Exécutez le script pour les modifications pour appliquer les nouvelles règles:

sudo chmod + x firewall-setup.sh 
sudo ./firewall-setup.sh

Remarque: L’ exécution de ces règles vous empêchera d’accéder à SSH pendant un court instant. C’est parce que nous bloquons tous les ports avant de définir les nouvelles règles, y compris SSH. Le verrouillage est temporaire (~ 10 secondes). Si, pour une raison quelconque, il ne se reconnecte pas, reconnectez-vous automatiquement via SSH.

Pour vous assurer que les règles sont automatiquement chargées au redémarrage, exécutez les opérations suivantes:

sudo invoke-rc.d netfilter-persistant enregistrer

Testez les nouvelles règles de pare-feu ont été appliquées:

sudo iptables -L

La fin

Nous sommes arrivés à la fin. Si tout fonctionnait correctement, vous devriez maintenant avoir un serveur NodeJS entièrement fonctionnel. Dans les prochains articles, j’aborderai plus en détail les différentes architectures de réseau et la sécurité.

Sources

Laisser un commentaire