Ignorer le certificat SSL auto-signé invalide dans node.js avec https.request?

309

Je travaille sur une petite application qui se connecte à mon routeur sans fil local (Linksys) mais je rencontre un problème avec le certificat SSL auto-signé du routeur.

J'ai exécuté wget 192.168.1.1 et j'ai obtenu:

ERROR: cannot verify 192.168.1.1's certificate, issued by `/C=US/ST=California/L=Irvine/O=Cisco-Linksys, LLC/OU=Division/CN=Linksys/[email protected]':
Self-signed certificate encountered.
ERROR: certificate common name `Linksys' doesn't match requested host name `192.168.1.1'.
To connect to 192.168.1.1 insecurely, use `--no-check-certificate'.

Dans le nœud, l'erreur détectée est:

{ [Error: socket hang up] code: 'ECONNRESET' }

Mon exemple de code actuel est:

var req = https.request({ 
    host: '192.168.1.1', 
    port: 443,
    path: '/',
    method: 'GET'

}, function(res){

    var body = [];
    res.on('data', function(data){
        body.push(data);
    });

    res.on('end', function(){
        console.log( body.join('') );
    });

});
req.end();

req.on('error', function(err){
    console.log(err);
});

Comment puis-je obtenir que node.js fasse l'équivalent de "--no-check-certificate"?

Geuis
la source

Réponses:

601

Réponse bon marché et peu sûre:

Ajouter

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

en code, avant d'appeler https.request()

Une manière plus sécurisée (la solution ci-dessus rend le processus de nœud entier non sécurisé) est répondue dans cette question

Juanra
la source
2
A fonctionné à merveille pour moi! J'ai placé ce code juste après avoir tout inclus dans le haut de mon application principale js.
Xedecimal
Cela a également fonctionné pour le combo NodeJS & SailJS. Je l'ai ajouté en haut de local.js
Michael Kork.
38
N'utilisez pas ceci ou "rejetez non autorisé" dans un environnement de production, car cela désactive toutes sortes de contrôles de sécurité.
Jason Walton
3
J'avais du mal à exécuter des tests à l'aide de mocha sur mon serveur de nœuds https auto-signé, et à l'ajouter immédiatement avant tout blocage de description pour faire passer mes tests.
artis3n
Ce n'est probablement pas le moyen le plus sûr de résoudre le problème. Voir stackoverflow.com/questions/20433287/…
Matt Pennington
166

Dans vos options de demande, essayez d'inclure les éléments suivants:

   var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      method: 'GET',
      rejectUnauthorized: false,
      requestCert: true,
      agent: false
    },
Meg Sharkey
la source
A travaillé pour moi. J'utilise restler et je vois qu'il n'a pas transmis les options par défaut, j'ai donc dû le patcher.
Olivier Amblet
2
Pour que cela fonctionne, vous devez fournir une instance explicite d'un agent personnalisé. Créez l'objet options et définissez l'agent: 'options.agent = new https.Agent (options);' Ensuite, appelez simplement 'https.request (options)'
Max
14
Eh bien, cela a fonctionné pour moi avec juste l' rejectUnauthorizedoption et rien d'autre
mcont
@mcont je confirme rejectUnauthorizedétait juste assez bon tout le reste ootb. Utilisation dans l'extension vs vs code. Mieux encore autoriser la configuration PEM, je le ferai ensuite ...
escape-llc
61

Ne croyez pas tous ceux qui essaient de vous induire en erreur.

Dans votre demande, ajoutez simplement:

ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})]

Si vous activez des certificats non autorisés, vous ne serez pas du tout protégé (exposé à MITM pour ne pas valider l'identité), et travailler sans SSL ne fera pas une grande différence. La solution consiste à spécifier le certificat CA que vous attendez, comme indiqué dans l'extrait de code suivant. Assurez-vous que le nom commun du certificat est identique à l'adresse que vous avez appelée dans la demande (comme spécifié dans l'hôte):

Vous obtiendrez alors:

var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})],
      method: 'GET',
      rejectUnauthorized: true,
      requestCert: true,
      agent: false
    },

Veuillez lire cet article (divulgation: article de blog écrit par l'auteur de cette réponse) ici afin de comprendre:

  • Fonctionnement des certificats CA
  • Comment générer facilement des certificats CA pour les tester afin de simuler l'environnement de production
Hesham Yassin
la source
7
Cela fonctionne et est la bonne façon de résoudre le problème «Erreur: certificat auto-signé dans la chaîne de certificats».
RohanRasane
1
pourquoi mettez-vous fs.readFileSync entre crochets, au lieu de le stocker sous forme de chaîne?
Lelo
Lelo: les crochets le transforment en tableau. ca: attend un tableau de certificats. Ce fichier doit être une liste de certificats séparés par des virgules, souvent les gens utilisent une fonction interne pour transformer un fichier PEM en tableau. Pour un auto signé, un seul certificat "devrait" fonctionner.
JohnDavid
53

Ajoutez la variable d'environnement suivante:

NODE_TLS_REJECT_UNAUTHORIZED=0

par exemple avec export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(avec un grand merci à Juanra)

Armand
la source
Cela a fonctionné pour moi lorsque j'essayais de courirwebdriver-manager update
Ashley
3
définir NODE_TLS_REJECT_UNAUTHORIZED = 0 pour Windows
Felipe SS
C'était une excellente solution pour mon environnement de développement
David
14

Ajout à la réponse @Armand:

Ajoutez la variable d'environnement suivante:

NODE_TLS_REJECT_UNAUTHORIZED = 0 par exemple avec export:

export NODE_TLS_REJECT_UNAUTHORIZED = 0 (avec un grand merci à Juanra)

Si vous utilisez Windows:

set NODE_TLS_REJECT_UNAUTHORIZED=0

Merci à: @ weagle08

IamStalker
la source
12

Vous pouvez également créer une instance de demande avec des options par défaut:

require('request').defaults({ rejectUnauthorized: false })
Eduardo
la source
3

Pour meteorJS, vous pouvez définir avec npmRequestOptions.

HTTP.post(url, {
    npmRequestOptions: {
        rejectUnauthorized: false // TODO remove when deploy
    },
    timeout: 30000, // 30s
    data: xml
}, function(error, result) {
    console.log('error: ' + error);
    console.log('resultXml: ' + result);
});
digz6666
la source
1

Ou vous pouvez essayer d'ajouter dans la résolution de nom locale ( hostsfichier trouvé dans le répertoire etcdans la plupart des systèmes d'exploitation, les détails diffèrent) quelque chose comme ceci:

192.168.1.1 Linksys 

et ensuite

var req = https.request({ 
    host: 'Linksys', 
    port: 443,
    path: '/',
    method: 'GET'
...

marchera.

piaf
la source
3
vrai que cela pourrait répondre à la question mais je pense que la prochaine erreur sera DEPTH_ZERO_SELF_SIGNED_CERT dans ce cas.
Olivier Amblet
1
alors comment contourner DEPTH_ZERO_SELF_SIGNED_CERT? Je rencontre ça maintenant.
reza
3
@reza: ajoutez ceci à vos options:rejectUnauthorized: false
Obay
1
Je sais que c'est un peu ancien mais pour référence future (afin de le faire correctement), vous devez obtenir un encodage PEM du certificat auto-signé et l'inclure dans les options en tant qu'autorité de certification (vous avez apparemment également besoin pour définir la valeur de l'agent mais cela peut être faux). Étant donné que le certificat est auto-signé, il agit comme sa propre autorité de certification et peut donc être utilisé pour se vérifier lui-même. Cependant, je me demandais également si cela valait vraiment la peine de le faire sur un routeur, car le firmware pourrait probablement être téléchargé et donc la clé privée pourrait être facilement compromise.
Jonathan Gray