¿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/[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'.

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"?

Geuis
fuente

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)

Juanra
fuente
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
    },
Meg Sharkey
fuente
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
Hesham Yassin
fuente
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)

Armand
fuente
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

IamStalker
fuente
12

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

require('request').defaults({ rejectUnauthorized: false })
Eduardo
fuente
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);
});
digz6666
fuente
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á.

piaf
fuente
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