Comment utiliser SSL / TLS avec Node.js – SitePoint


En 2020, il n’y a aucune raison pour que votre site Web n’utilise pas HTTPS. Les visiteurs l’attendent, Google l’utilise comme facteur de classement et les fabricants de navigateurs nommeront et honteusement les sites qui ne l’utilisent pas.

Dans ce didacticiel, je vais vous expliquer comment ajouter un Cryptons– certificat généré sur votre serveur Express.js.

Mais la protection de nos sites et applications avec HTTPS ne suffit pas. Nous devons également exiger des connexions chiffrées des serveurs avec lesquels nous parlons. Nous verrons qu’il existe des possibilités d’activer la couche SSL / TLS même si elle n’est pas activée par défaut.

Remarque: si vous recherchez des instructions sur la façon de configurer SSL avec NGINX lors de sa configuration pour qu’il fonctionne comme proxy inverse pour une application Node, consultez notre astuce rapide, “Configuration de NGINX et SSL avec Node.js”.

Commençons par un bref examen de l’état actuel de HTTPS.

HTTPS partout

La spécification HTTP / 2 a été publié en tant que RFC 7540 en mai 2015, ce qui signifie qu’à ce stade, il fait partie de la norme. Ce fut une étape importante. Maintenant, nous pouvons tous mettre à niveau nos serveurs pour utiliser HTTP / 2. L’un des aspects les plus importants est la rétrocompatibilité avec HTTP 1.1 et le mécanisme de négociation pour choisir un protocole différent. Bien que la norme ne spécifie pas de chiffrement obligatoire, aucun navigateur ne prend actuellement en charge HTTP / 2 non chiffré. Cela donne au HTTPS un nouvel élan. Enfin, nous aurons le HTTPS partout!

À quoi ressemble réellement notre pile? Du point de vue d’un site Web fonctionnant dans le navigateur (au niveau de l’application), nous devons traverser les couches suivantes pour atteindre le niveau IP:

  1. Navigateur client
  2. HTTP
  3. SSL / TLS
  4. TCP
  5. IP

HTTPS n’est rien de plus que le protocole HTTP au-dessus de SSL / TLS. Par conséquent, toutes les règles HTTP s’appliquent toujours. Que nous apporte réellement cette couche supplémentaire? Les avantages sont multiples: nous obtenons l’authentification en ayant des clés et des certificats; un certain type d’intimité et de confidentialité est garanti, car la connexion est cryptée de manière asymétrique; et l’intégrité des données est également préservée, car les données transmises ne peuvent pas être modifiées pendant le transit.

L’un des mythes les plus courants est que l’utilisation de SSL / TLS coûte cher en calcul et ralentit le serveur. Ce n’est certainement plus vrai. Nous n’avons pas non plus besoin de matériel spécialisé avec des unités de cryptographie. Même pour Google, la couche SSL / TLS représente moins de 1% de la charge CPU et la surcharge réseau de HTTPS par rapport à HTTP est inférieure à 2%. Dans l’ensemble, il ne serait pas logique de renoncer au HTTPS pour un peu de frais généraux.

Comme le dit Ilya Grigorik, il n’y a qu’un problème de performance:

La version la plus récente est TLS 1.3. TLS est le successeur de SSL, qui est disponible dans sa dernière version SSL 3.0. Les modifications de SSL à TLS empêchent l’interopérabilité, mais la procédure de base reste cependant inchangée. Nous avons trois canaux cryptés différents. Le premier est une infrastructure à clé publique pour les chaînes de certificats. Le second fournit une cryptographie à clé publique pour les échanges de clés. Enfin, le troisième est symétrique. Ici, nous avons la cryptographie pour les transferts de données.

TLS 1.3 utilise le hachage pour certaines opérations importantes. Théoriquement, il est possible d’utiliser n’importe quel algorithme de hachage, mais il est fortement recommandé d’utiliser SHA2 ou un algorithme plus puissant. SHA1 est un standard depuis longtemps mais est récemment devenu obsolète.

HTTPS gagne également plus d’attention pour les clients. Les problèmes de confidentialité et de sécurité ont toujours existé, mais avec la quantité croissante de données et de services accessibles en ligne, les gens sont de plus en plus préoccupés. Pour les sites qui ne l’implémentent pas, il existe une extension de navigateur utile – HTTPS partout depuis l’EFF – qui crypte nos communications avec la plupart des sites Web.

HTTPS-partout

Les créateurs ont réalisé que de nombreux sites Web n’offrent le HTTPS que partiellement. Le plugin nous permet de réécrire les demandes pour les sites qui n’offrent qu’une prise en charge HTTPS partielle. Alternativement, nous pouvons également bloquer HTTP complètement (voir la capture d’écran ci-dessus).

Communication de base

Le processus de validation du certificat implique la validation de la signature et de l’expiration du certificat. Nous devons également vérifier qu’il s’enchaîne à une racine de confiance. Enfin, nous devons vérifier si elle a été révoquée. Il existe des autorités dédiées et fiables dans le monde qui accordent des certificats. Dans le cas où l’un de ceux-ci deviendrait compromis, tous les autres certificats de ladite autorité seraient révoqués.

Le diagramme de séquence d’une négociation HTTPS se présente comme suit. Nous commençons par l’initialisation du client, qui est suivie d’un message avec le certificat et l’échange de clés. Une fois que le serveur a envoyé son package terminé, le client peut démarrer l’échange de clés et la transmission des spécifications de chiffrement. À ce stade, le client est terminé. Enfin, le serveur confirme la sélection de la spécification de chiffrement et ferme la négociation.

Séquence HTTPS

La séquence entière est déclenchée indépendamment de HTTP. Si nous décidons d’utiliser HTTPS, seule la gestion des sockets est modifiée. Le client émet toujours des requêtes HTTP, mais le socket effectuera la prise de contact décrite précédemment et chiffrera le contenu (en-tête et corps).

Alors, de quoi avons-nous besoin pour faire fonctionner SSL / TLS avec un serveur Express.js?

HTTPS

Par défaut, Node.js sert le contenu via HTTP. Mais il y a aussi un Module HTTPS que nous devons utiliser pour communiquer sur un canal sécurisé avec le client. Il s’agit d’un module intégré, et l’utilisation est très similaire à la façon dont nous utilisons le module HTTP:

const https = require("https"),
  fs = require("fs");

const options = {
  key: fs.readFileSync("/srv/www/keys/my-site-key.pem"),
  cert: fs.readFileSync("/srv/www/keys/chain.pem")
};

const app = express();

app.use((req, res) => {
  res.writeHead(200);
  res.end("hello worldn");
});

app.listen(8000);

https.createServer(options, app).listen(8080);

Ignore le /srv/www/keys/my-site-key.pem et et /srv/www/keys/chain.pem fichiers pour le moment. Ce sont les certificats SSL que nous devons générer, ce que nous ferons un peu plus tard. C’est la partie qui a changé avec Let’s Encrypt. Auparavant, nous devions générer une paire de clés privée / publique, l’envoyer à une autorité de confiance, les payer et probablement attendre un peu pour obtenir un certificat SSL. De nos jours, Let’s Encrypt génère et valide instantanément vos certificats gratuitement!

Génération de certificats

Certbot

La spécification TLS requiert un certificat, qui est signé par une autorité de certification (CA) de confiance. L’AC s’assure que le titulaire du certificat est bien celui qu’il prétend être. Donc, fondamentalement, lorsque vous voyez l’icône de verrouillage verte (ou tout autre signe verdâtre sur le côté gauche de l’URL dans votre navigateur), cela signifie que le serveur avec lequel vous communiquez est vraiment celui qu’il prétend être. Si vous êtes sur facebook.com et que vous voyez un cadenas vert, il est presque certain que vous communiquez vraiment avec Facebook et que personne d’autre ne peut voir votre communication – ou plutôt, personne d’autre ne peut la lire.

Il convient de noter que ce certificat ne doit pas nécessairement être vérifié par une autorité telle que Let’s Encrypt. Il existe également d’autres services payants. Vous pouvez techniquement le signer vous-même, mais ensuite (comme vous n’êtes pas une autorité de certification de confiance), les utilisateurs visitant votre site verront probablement une large offre d’avertissement effrayante pour les remettre en sécurité.

Dans l’exemple suivant, nous utiliserons le Certbot, qui est utilisé pour générer et gérer des certificats avec Let’s Encrypt.

Sur le site Certbot vous pouvez trouver des instructions sur la façon d’installer Certbot pour presque toutes les combinaisons OS / serveur. Vous devez choisir les options qui vous sont applicables.

Une combinaison courante pour déployer des applications Node est NGINX sur le dernier Ubuntu LTS et c’est ce que j’utiliserai ici.

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update

Webroot

Webroot est un plugin Certbot qui, en plus de la fonctionnalité par défaut de Certbot (qui génère automatiquement votre paire de clés publique / privée et génère un certificat SSL pour celles-ci), copie également les certificats dans votre dossier webroot et vérifie votre serveur en plaçant du code de vérification dans un répertoire temporaire caché nommé .well-known. Pour ignorer certaines de ces étapes manuellement, nous utiliserons ce plugin. Le plugin est installé par défaut avec Certbot. Afin de générer et de vérifier nos certificats, nous exécuterons les éléments suivants:

certbot certonly --webroot -w /var/www/example/ -d www.example.com -d example.com

Vous devrez peut-être exécuter cette commande en tant que sudo, car elle essaiera d’écrire dans /var/log/letsencrypt.

On vous demandera également votre adresse e-mail. C’est une bonne idée de saisir une adresse réelle que vous utilisez souvent, car vous recevrez une notification si votre certificat est sur le point d’expirer. Le compromis pour Let’s Encrypt émettant un certificat gratuit est qu’il expire tous les trois mois. Heureusement, le renouvellement est aussi simple que d’exécuter une commande simple, que nous pouvons affecter à un travail cron et ne pas avoir à se soucier de l’expiration. De plus, le renouvellement des certificats SSL est une bonne pratique de sécurité, car cela laisse moins de temps aux attaquants pour casser le chiffrement. Parfois, les développeurs configurent même ce cron pour qu’il s’exécute quotidiennement, ce qui est tout à fait correct et même recommandé.

N’oubliez pas que vous devez exécuter cette commande sur un serveur sur lequel le domaine spécifié sous le -d (pour le domaine), l’indicateur se résout, c’est-à-dire votre serveur de production. Même si vous avez la résolution DNS dans votre fichier d’hôtes local, cela ne fonctionnera pas, car le domaine sera vérifié de l’extérieur. Donc, si vous le faites localement, cela échouera très probablement, à moins que vous n’ouvriez un port de votre machine locale vers le monde extérieur et que vous le fassiez tourner derrière un nom de domaine qui résout votre machine. Il s’agit d’un scénario hautement improbable.

Enfin et surtout, après avoir exécuté cette commande, la sortie contiendra les chemins d’accès à vos fichiers de clé privée et de certificat. Copiez ces valeurs dans l’extrait de code précédent – dans le cert propriété pour le certificat, et key propriété de la clé:

// ...

const options = {
  key: fs.readFileSync("/var/www/example/sslcert/privkey.pem"),
  cert: fs.readFileSync("/var/www/example/sslcert/fullchain.pem") // these paths might differ for you, make sure to copy from the certbot output
};

// ...

Tighetning It Up

HTTP Strict Transport Security

Avez-vous déjà eu un site Web sur lequel vous êtes passé de HTTP à HTTPS et il y avait encore des redirections résiduelles redirigeant vers HTTP? HTTP Strict Transport Security (HSTS) est un mécanisme de politique de sécurité Web pour atténuer les attaques de déclassement de protocole et le détournement de cookies.

HSTS oblige efficacement le client (navigateur accédant à votre serveur) à diriger tout le trafic via HTTPS – une idéologie «sécurisée ou pas du tout»!

Express JS ne nous permet pas d’ajouter cet en-tête par défaut, nous allons donc utiliser Casque, un module Node qui nous permet de le faire. Installer Casque en exécutant ce qui suit:

npm install helmet

Il suffit ensuite de l’ajouter en tant que middleware à notre serveur Express:

const https = require("https"),
  fs = require("fs"),
  helmet = require("helmet");

const options = {
  key: fs.readFileSync("/srv/www/keys/my-site-key.pem"),
  cert: fs.readFileSync("/srv/www/keys/chain.pem")
};

const app = express();

app.use(helmet()); // Add Helmet as a middleware

app.use((req, res) => {
  res.writeHead(200);
  res.end("hello worldn");
});

app.listen(8000);

https.createServer(options, app).listen(8080);

Paramètres Diffie – Hellman Strong (er)

Pour sauter des maths compliquées, passons à la chasse. En termes très simples, deux clés différentes sont utilisées pour le chiffrement: le certificat que nous obtenons de l’autorité de certification et celui généré par le serveur pour l’échange de clés. La clé par défaut pour l’échange de clés (également appelée Échange de clés Diffie – Hellman, ou DH) utilise une clé «plus petite» que celle du certificat. Pour y remédier, nous allons générer une clé DH forte et la transmettre à notre serveur sécurisé pour utilisation.

Pour générer une clé plus longue (2048 bits), vous aurez besoin openssl, que vous avez probablement installé par défaut. En cas de doute, lancez openssl -v. Si la commande est introuvable, installez openssl en exécutant sudo apt install openssl (ou visitez leur page de téléchargement ici):

openssl dhparam -out /var/www/example/sslcert/dh-strong.pem 2048

Copiez ensuite le chemin d’accès au fichier dans notre configuration:

// ...

const options = {
  key: fs.readFileSync("/var/www/example/sslcert/privkey.pem"),
  cert: fs.readFileSync("/var/www/example/sslcert/fullchain.pem"), // these paths might differ for you, make sure to copy from the certbot output
  dhparam: fs.readFileSync("/var/www/example/sslcert/dh-strong.pem")
};

// ...

Conclusion

En 2020 et au-delà, il n’y a aucune excuse pour rejeter HTTPS. La direction future est clairement visible: HTTPS partout! Dans Node.js, nous avons beaucoup d’options pour utiliser SSL / TLS. Nous pouvons publier nos sites Web en HTTPS, nous pouvons créer des demandes pour des sites Web chiffrés et nous pouvons autoriser des certificats par ailleurs non fiables.



Close Menu