Fermer

avril 9, 2020

Comment utiliser SSL / TLS avec Node.js –


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 seront heureux de nommer et de faire honte aux sites qui ne l'utilisent pas.

Dans ce didacticiel, je vais vous expliquer comment ajouter un Cryptez le certificat généré par 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 cherchez des instructions sur la façon de configurer SSL avec NGINX lors de sa configuration pour fonctionner en tant que proxy inverse pour une application Node, consultez notre astuce, « Configuration de NGINX et SSL avec Node.js ».

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

HTTPS Everywhere

La ​​spécification HTTP / 2 a été publiée en tant que RFC 7540 en mai 2015, ce qui signifie qu'à ce stade, elle 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 [19659010] IP

HTTPS n'est rien de plus que le protocole HTTP en plus 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 seul problème de performances:

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.

Le 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 Everywhere from the EFF – qui crypte nos communications avec la plupart des sites Web.

 HTTPS-partout [19659003] 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 (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 prise de contact 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 que SSL / TLS fonctionne avec un serveur Express.js? [19659030] HTTPS

Par défaut, Node.js sert le contenu sur HTTP. Mais il existe également un module HTTPS que nous devons utiliser pour communiquer sur un canal sécurisé avec le client. Ceci est 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 ("bonjour le monde  n");
});

app.listen (8000);

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

Ignorez les fichiers /srv/www/keys/my-site-key.pem et et /srv/www/keys/chain.pem 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 exige 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 (comme vous n'êtes pas une autorité de confiance), les utilisateurs visitant votre site verront probablement une large offre d'avertissement effrayante pour les remettre en sécurité.

Dans le 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 trouverez des instructions sur la façon d'installer Certbot pour presque toutes les combinaisons OS / serveur. Vous devez choisir les options qui vous concernent.

Une combinaison courante pour le déploiement des applications Node est NGINX sur la dernière LTS Ubuntu et c'est ce que j'utiliserai ici.

 sudo apt-get update
sudo apt-get install software-properties-common
univers sudo add-apt-repository
sudo add-apt-repository ppa: certbot / certbot
mise à jour sudo apt-get

Webroot

Webroot est un plugin Certbot qui, en plus de la fonctionnalité par défaut 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 sur votre webroot et vérifie votre serveur en plaçant du code de vérification dans un répertoire temporaire caché nommé .connu . 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 ce qui suit:

 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 .

Il vous sera également demandé 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 assigner à une tâche cron sans 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 -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 la propriété cert pour le certificat et dans la propriété key pour la clé:

 // ...

const options = {
  key: fs.readFileSync ("/ var / www / example / sslcert / privkey.pem"),
  cert: fs.readFileSync ("/ var / www / example / sslcert / fullchain.pem") // ces chemins peuvent différer pour vous, assurez-vous de copier à partir de la sortie certbot
};

// ...

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 des redirections résiduelles qui redirigeaient toujours 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 – un

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

 npm install casque

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

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

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 (casque ()); // Ajouter un casque comme middleware

app.use ((req, res) => {
  res.writeHead (200);
  res.end ("bonjour le monde  n");
});

app.listen (8000);

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

Paramètres Diffie – Hellman Strong (er)

Pour éviter des calculs compliqués, 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.

Afin de générer une clé plus longue (2048 bits), vous aurez besoin de openssl , que vous avez probablement installé par défaut. En cas de doute, exécutez openssl -v . Si la commande n'est pas trouvée, 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"), // ces chemins peuvent différer pour vous, assurez-vous de copier à partir de la sortie certbot
  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 approuvés.






Source link