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 443
au port de l’application NodeJS (dans ce tutoriel , nous courons 3 instances de l’application sur les ports 5001
, 5002
, 5003
) 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
root
connexion 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 git
ou 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 dns
prouverons 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-mailyour-domain.com
: Définissez ceci sur votre nom de domainewww.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 TXT
enregistrements à votre nom de domaine avec des instructions sur ce qu’il faut ajouter (sur les TXT
enregistrements Digital Ocean peuvent être ajoutés dans le panneau de contrôle). Après avoir ajouté les TXT
enregistrements, 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 renew
permettra de renouveler les certificats non valides. Si un certificat doit expirer dans les 30 jours, il certbot
sera 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-hook
argument 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.com
de 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.com
votre domaine et toutes les instances de public_id
l’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:
- https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts
- https://www.haproxy.org/download/1.4/doc/configuration.txt
- https://www.youtube.com/watch?v=oqvKDbrF-TA&spfreload=10
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
,start
etreload
l’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=web
et Group=web
au 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 start
, stop
et reload
l’application:
sudo systemctl démarrer nodeapp
sudo systemctl arrêter nodeapp
sudo systemctl recharger nodeapp
… et utilisez journalctl
pour 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é.