¿Ignorar el certificado SSL autofirmado no válido en node.js con https.request?


309

Estoy trabajando en una pequeña aplicación que inicia sesión en mi enrutador inalámbrico local (Linksys) pero tengo un problema con el certificado SSL autofirmado del enrutador.

Ejecuté wget 192.168.1.1 y obtuve:

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/emailAddress=support@linksys.com':
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'.

En el nodo, el error que se detecta es:

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

Mi código de muestra actual es:

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);
});

¿Cómo puedo hacer para que node.js haga el equivalente de "--no-check-certificate"?

Respuestas:


601

Respuesta barata e insegura:

Añadir

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

en código, antes de llamar https.request()

En esta pregunta se responde una forma más segura (la solución anterior hace que todo el proceso del nodo sea inseguro)


2
¡Funcionó como un encanto para mí! Coloqué este código justo después de incluir todo en la parte superior de mi aplicación principal js.
Xedecimal

Esto también funcionó para el combo NodeJS & SailJS. Lo agregué en la parte superior de local.js
Michael Kork.

38
No utilice esto o "rechazar no autorizado" en un entorno de producción, ya que esto deshabilita todo tipo de controles de seguridad.
Jason Walton el

3
Estaba teniendo problemas para ejecutar pruebas usando mocha en mi servidor de nodo https autofirmado, y agregué esto inmediatamente antes de que cualquier bloque de descripción hiciera pasar mis pruebas.
artis3n

Probablemente esta no sea la forma más segura de solucionar el problema. Ver stackoverflow.com/questions/20433287/…
Matt Pennington el

166

En sus opciones de solicitud, intente incluir lo siguiente:

   var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      method: 'GET',
      rejectUnauthorized: false,
      requestCert: true,
      agent: false
    },

Trabajó para mi. Uso restler y veo que no reenvió las opciones por defecto, así que tuve que parchearlo.
Olivier Amblet

2
Para que esto funcione, debe proporcionar una instancia explícita de un agente personalizado. Cree el objeto de opciones y establezca el agente: 'options.agent = new https.Agent (options);' Luego simplemente llame a 'https.request (opciones)'
Max

14
Bueno, esto funcionó para mí solo con la rejectUnauthorizedopción y nada más
mcont

@mcont confirmo que rejectUnauthorizedfue lo suficientemente bueno todo lo demás ootb. Uso dentro de la extensión de código vs. Mejor aún, permita la configuración de PEM, lo haré después ...
escape-llc

61

No creas a todos los que intentan engañarte

En su solicitud, solo agregue:

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

Si activa certificados no autorizados, no estará protegido (expuesto a MITM por no validar la identidad), y trabajar sin SSL no será una gran diferencia. La solución es especificar el certificado de CA que espera como se muestra en el siguiente fragmento. Asegúrese de que el nombre común del certificado sea idéntico a la dirección que llamó en la solicitud (como se especifica en el host):

Lo que obtendrá entonces es:

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
    },

Lea este artículo (divulgación: publicación de blog escrita por el autor de esta respuesta) aquí para comprender:

  • Cómo funcionan los certificados de CA
  • Cómo generar CA Certs para realizar pruebas fácilmente con el fin de simular el entorno de producción

77
Esto funciona y es la forma correcta de solucionar el problema "Error: certificado autofirmado en la cadena de certificados".
RohanRasane

1
¿por qué pones fs.readFileSync entre corchetes, en lugar de almacenarlo como una cadena?
Lelo

Lelo: los corchetes lo convierten en una matriz. ca: espera una serie de certs. Este archivo debe ser una lista de certs separados por comas, a menudo las personas usan una función interna para convertir un archivo PEM en una matriz. Para un cet autofirmado, un solo certificado "debería" funcionar.
JohnDavid

53

Agregue la siguiente variable de entorno:

NODE_TLS_REJECT_UNAUTHORIZED=0

por ejemplo con export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(con muchas gracias a Juanra)


Esto funcionó para mí cuando trataba de correrwebdriver-manager update
Ashley

3
establecer NODE_TLS_REJECT_UNAUTHORIZED = 0 para windows
Felipe SS

Esta fue una gran solución para mi entorno de desarrollo
David

14

Agregando a @Armand respuesta:

Agregue la siguiente variable de entorno:

NODE_TLS_REJECT_UNAUTHORIZED = 0 por ejemplo, con exportación:

export NODE_TLS_REJECT_UNAUTHORIZED = 0 (con muchas gracias a Juanra)

Si usa Windows:

set NODE_TLS_REJECT_UNAUTHORIZED=0

Gracias a: @ weagle08


12

También puede crear una instancia de solicitud con opciones predeterminadas:

require('request').defaults({ rejectUnauthorized: false })

3

Para meteorJS puede configurar con 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);
});

1

O puede intentar agregar una resolución de nombre local (el hostsarchivo se encuentra en el directorio etcen la mayoría de los sistemas operativos, los detalles difieren) algo como esto:

192.168.1.1 Linksys 

y después

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

trabajará.


3
Es cierto que esto podría responder la pregunta, pero creo que el siguiente error será DEPTH_ZERO_SELF_SIGNED_CERT en este caso.
Olivier Amblet

1
Entonces, ¿cómo se puede moverse DEPTH_ZERO_SELF_SIGNED_CERT? Me estoy encontrando con eso ahora.
reza

3
@reza: agregue esto a sus opciones:rejectUnauthorized: false
Obay

1
Sé que esto es un poco viejo, pero para referencia futura (para hacer esto de la manera correcta), debe obtener una codificación PEM del certificado autofirmado e incluirlo en las opciones como CA (aparentemente también necesita para establecer el valor del agente pero eso puede ser falso). Dado que el certificado es autofirmado, actúa como su propia CA y, por lo tanto, se puede utilizar para verificarlo. Sin embargo, también me preguntaría si realmente valdría la pena hacerlo en un enrutador, ya que el firmware probablemente podría descargarse y, por lo tanto, la clave privada podría verse fácilmente comprometida.
Jonathan Gray
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.