Impossibile verificare la firma foglia


142

Sto usando node.js request.js per raggiungere un API. Ricevo questo errore

[Errore: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Tutte le mie credenziali sono accurate e valide e il server va bene. Ho fatto la stessa richiesta con il postino.

request({
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Questo codice è in esecuzione in uno script eseguibile ex. node ./run_file.js, È per questo? Deve essere eseguito su un server?


Questa è una possibilità, ma potrebbe essere che l'API non riconosca l'agente utente passato dal programma del nodo?
Hector Correa,


@HectorCorrea Sono stato in grado di leggere perfettamente l'API nel postino. Perché il nodo non può farlo? Ho provato a cambiare l'agente utente, senza fortuna.
ThomasReggi,

Risposte:


157

Nota : quanto segue è pericoloso e consentirà di intercettare e modificare il contenuto dell'API tra il client e il server.

Anche questo ha funzionato

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';


22
L'ho sollevato, e grazie per aver risposto, ma è attivamente dannoso per la tua sicurezza. Di seguito è necessario aggiungere la CA mancante per la risposta di @ CoolAJ86.
mikemaccana,

4
Sto usando le NodeJS plugin chiamato nodemailered nodemailer-smtp-transporte lo stesso comando generale lavorato. Devi aggiungere questo al tuo createTransportoggetto:tls:{rejectUnauthorized: false}
LukeP

3
Immagino che @LukeP sia altrettanto insicuro con nodemailer. C'è un indizio nel nome: se qualcosa è autorizzato dall'ONU , in genere si desidera rifiutarlo, per definizione. Ciò di cui hai bisogno è trovare un modo per autorizzarlo correttamente (impostando correttamente i certificati CA, come hanno già detto altre risposte).
Bruno,

@Bruno Sono d'accordo, dovresti configurarlo nel modo giusto con i certificati. Volevo semplicemente impostare un test rapido per una demo, quindi il codice che ho pubblicato è una soluzione rapida. Avrei dovuto prefigurarlo nel mio commento.
LukeP

1
@mikemaccana Non ci sono problemi di sicurezza se la richiesta si trova sullo stesso server e sei l'unico proprietario.
Binar Web,

89

Non è un problema con l'applicazione, ma con il certificato che è firmato da una CA intermedia. Se si accetta questo fatto e si desidera continuare, aggiungere quanto segue per richiedere le opzioni:

rejectUnauthorized: false

Richiesta completa:

request({
    "rejectUnauthorized": false,
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Ho questo problema adesso al lavoro. Ho inviato un ticket IT che informa che SSL potrebbe essere configurato in modo errato - mi hanno detto che ero bramoso. Ci sono ulteriori informazioni che posso dare loro per risolvere questo problema?
Blakev,

In realtà non è corretto: come menzionano CoolAJ86 e hectorcorrea, il certificato è valido, ma è firmato da una CA intermedia.
mikemaccana,

80

La soluzione sicura

Invece di disattivare la sicurezza, è possibile aggiungere i certificati necessari alla catena. Prima installa il pacchetto ssl-root-cas da npm:

npm install ssl-root-cas

Questo pacchetto contiene molti certificati intermedi di cui i browser si fidano ma il nodo no.

var sslRootCAs = require('ssl-root-cas/latest')
sslRootCAs.inject()

Aggiungerà i certificati mancanti. Per maggiori informazioni vedere qui:

https://git.coolaj86.com/coolaj86/ssl-root-cas.js

Inoltre, vedi la risposta successiva di seguito


2
Il client Http non utilizza l'archivio certificati Autorità di certificazione radice Trusted Windows?
Richard Collette,

1
Il nodo usa i certs mozilla raggruppati nel file binario e li sovrascrive ogni volta che si fornisce il proprio caarray. Non so se il suo modulo http guarderà anche alla catena del sistema operativo. Tuttavia, l'arricciatura su OS X sembra utilizzare solo la catena del sistema operativo e non consentire certs specificati manualmente.
coolaj86

Deve essere eseguito per ogni processo o posso eseguirlo una volta e aggiornare i miei certificati a livello globale?
Joshua Snider

I certificati sono memorizzati in due potenziali posti: (1) incorporato nel file binario node.js (2) nel keystore del sistema operativo. Se i tuoi certificati non sono aggiornati, dovrai includerli nel codice corrente. Non cambia il nodo binario né il sistema operativo, ma solo la cartella del progetto.
coolaj86

1
@Sunkas È esattamente ciò che dicono i messaggi di errore. Non so come spiegarlo in modo più semplice. È un file di sola lettura e non può essere modificato.
coolaj86,

45

La soluzione di CoolAJ86 è corretta e non compromette la sicurezza come disabilitare tutti i controlli con rejectUnauthorizedo NODE_TLS_REJECT_UNAUTHORIZED. Tuttavia, potrebbe essere necessario iniettare esplicitamente un certificato CA aggiuntivo.

Ho provato prima le CA principali incluse dal modulo ssl-root-cas :

require('ssl-root-cas/latest')
  .inject();

Ho ancora finito con l' UNABLE_TO_VERIFY_LEAF_SIGNATUREerrore. Poi ho scoperto chi ha emesso il certificato per il sito Web a cui mi collegavo con l' analizzatore SSL COMODO , ho scaricato il certificato di tale autorità e ho provato ad aggiungere solo quello:

require('ssl-root-cas/latest')
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

Ho finito con un altro errore: CERT_UNTRUSTED. Infine, ho iniettato le CA radice aggiuntive e ho incluso la "mia" CA (apparentemente intermediata), che ha funzionato:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

1
Mi stavo connettendo a un sito Web con un certificato rilasciato dal CA COMODO High-Assurance Secure Server. Ho scaricato il certificato dalla loro pagina di download .
Ferdinand Prantl,

2
Grazie! Per il mio problema, ho dovuto aggiungere l'intera catena di certificati per superare questo errore. Per altri riferimenti, questo post mi ha mostrato come esportare facilmente i file pem necessari tramite Firefox: superuser.com/a/97203
mfink

Bene grazie per l'aiuto. Nel mio caso, alla fine era una cattiva configurazione del server SSL, non del nodo. Non tutti i certificati intermedi sono stati installati sul server.
Scott Jungwirth,

se ottieni il certificato mentre .ceresegui questo openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crtper convertirlo in .crtanticipo
0x1gene

8

Per Creare un'app React (dove si verifica anche questo errore e questa domanda è il risultato n. 1 di Google), probabilmente stai usando HTTPS=true npm starte un proxy(in package.json) che va ad alcune API HTTPS che è autofirmato, quando in fase di sviluppo.

In tal caso, considera di cambiare in proxyquesto modo:

"proxy": {
  "/api": {
    "target": "https://localhost:5001",
    "secure": false
  }
}

secure decide se il proxy WebPack controlla o meno la catena di certificati e disabilita ciò per garantire che il certificato autofirmato dell'API non sia verificato in modo da ottenere i dati.


4

Potrebbe essere molto allettante fare rejectUnauthorized: falseo process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';ma non farlo! Ti espone all'uomo in mezzo agli attacchi.

Le altre risposte sono corrette in quanto il problema risiede nel fatto che il certificato è "firmato da una CA intermedia". Esiste una soluzione semplice a questa, una che non richiede una libreria di terze parti come ssl-root-caso iniettare eventuali CA aggiuntive nel nodo.

La maggior parte dei client https nelle opzioni di supporto del nodo consente di specificare una CA per richiesta, che verrà risolta UNABLE_TO_VERIFY_LEAF_SIGNATURE. Ecco un semplice esempio usando il httpsmodulo integrato del nodo .

import https from 'https';

const options = {
  host: '<your host>',
  defaultPort: 443,
  path: '<your path>',
  // assuming the bundle file is co-located with this file
  ca: readFileSync(__dirname + '/<your bundle file>.ca-bundle'),
  headers: {
    'content-type': 'application/json',
  }
};
https.get(options, res => {
  // do whatever you need to do
})

Se, tuttavia, è possibile configurare le impostazioni SSL nel server di hosting, la soluzione migliore sarebbe quella di aggiungere i certificati intermedi al provider di hosting. In questo modo il richiedente client non ha bisogno di specificare una CA, poiché è inclusa nel server stesso. Personalmente uso namecheap + heroku. Il trucco per me era creare un file .crt con cat yourcertificate.crt bundle.ca-bundle > server.crt. Ho quindi aperto questo file e aggiunto una nuova riga dopo il primo certificato. Puoi leggere di più su

https://www.namecheap.com/support/knowledgebase/article.aspx/10050/33/installing-an-ssl-certificate-on-heroku-ssl


Questo bug arriva principalmente nell'ambiente locale, non in produzione, quindi se sei in locale va bene: process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
Vivex,

@Vivex: non va bene farlo in un ambiente locale se l'intero punto è testare come funzionano i certificati SSL e come vengono fatti passare ...
dwanderson

2

Metto questo qui nel caso in cui aiuti qualcuno, il mio caso era diverso e un po 'strano. Lo stavo ottenendo su una richiesta a cui si accedeva tramite un superagent : il problema non aveva nulla a che fare con i certificati (che erano stati impostati correttamente) e tutto dipendeva dal fatto che stavo passando il risultato superagente attraverso il callback a cascata del modulo asincrono . Per risolvere: invece di passare l'intero risultato, basta result.bodyattraversare il callback della cascata.


2

Ho avuto gli stessi problemi. Ho seguito la soluzione @ThomasReggi e @ CoolAJ86 e ho funzionato bene ma non sono soddisfatto della soluzione.

Perché il problema "UNABLE_TO_VERIFY_LEAF_SIGNATURE" si è verificato a causa del livello di configurazione della certificazione.

Accetto la soluzione @thirdender ma la sua soluzione parziale. Come per il sito Web ufficiale nginx , hanno chiaramente indicato che il certificato dovrebbe essere una combinazione del certificato del server e dei certificati concatenati.

inserisci qui la descrizione dell'immagine


2

Puoi anche provare impostando strictSSL su false, in questo modo:

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}

Funziona se invii dall'applicazione Node JS, fantastico !!
Ally Makongo

0

Ho avuto un problema con la mia configurazione di Apache dopo aver installato un certificato GoDaddy su un sottodominio. Inizialmente pensavo che potesse essere un problema con Node che non inviava un Server Name Indicator (SNI), ma non era così. L'analisi del certificato SSL del sottodominio con https://www.ssllabs.com/ssltest/ ha restituito l'errore Problemi relativi alla catena: incompleti .

Dopo aver aggiunto il gd_bundle-g2-g1.crtfile fornito da GoDaddy tramite la SSLCertificateChainFiledirettiva Apache, Node è stato in grado di connettersi tramite HTTPS e l'errore è scomparso.


0

Devi includere il certificato intermedio nel tuo server. Questo risolve il [Errore: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


0

Un altro approccio per risolverlo in modo sicuro è utilizzare il seguente modulo.

node_extra_ca_certs_mozilla_bundle

Questo modulo può funzionare senza alcuna modifica del codice generando un file PEM che include tutti i certificati root e intermedi considerati affidabili da Mozilla. È possibile utilizzare la seguente variabile di ambiente (funziona con Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Per generare il file PEM da utilizzare con la variabile di ambiente sopra. È possibile installare il modulo utilizzando:

npm install --save node_extra_ca_certs_mozilla_bundle

e quindi avvia lo script del nodo con una variabile di ambiente.

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

Altri modi per utilizzare il file PEM generato sono disponibili su:

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

NOTA: sono l'autore del modulo sopra.


0

Se vieni a questo thread perché stai utilizzando il modulo postgres / pg del nodo, c'è una soluzione migliore rispetto all'impostazione NODE_TLS_REJECT_UNAUTHORIZEDo rejectUnauthorized, che porterà a connessioni non sicure.

Invece, configura l'opzione "ssl" in modo che corrisponda ai parametri per tls.connect :

{
  ca: fs.readFileSync('/path/to/server-ca.pem').toString(),
  cert: fs.readFileSync('/path/to/client-cert.pem').toString(),
  key: fs.readFileSync('/path/to/client-key.pem').toString(),
  servername: 'my-server-name' // e.g. my-project-id/my-sql-instance-id for Google SQL
}

Ho scritto un modulo per aiutare con l'analisi di queste opzioni da variabili d'ambiente, come PGSSLROOTCERT, PGSSLCERTe PGSSLKEY:

https://github.com/programmarchy/pg-ssl


-1

I seguenti comandi hanno funzionato per me:

> npm config set strict-ssl false
> npm cache clean --force

Il problema è che si sta tentando di installare un modulo da un repository con un certificato SSL [Secure Sockets Layer] errato o non attendibile. Dopo aver pulito la cache, questo problema verrà risolto. Potrebbe essere necessario trasformarlo in true in seguito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.