Ungültiges selbstsigniertes SSL-Zertifikat in node.js mit https.request ignorieren?

309

Ich arbeite an einer kleinen App, die sich bei meinem lokalen WLAN-Router (Linksys) anmeldet, aber ich habe ein Problem mit dem selbstsignierten SSL-Zertifikat des Routers.

Ich lief wget 192.168.1.1 und bekam:

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'.

Im Knoten wird folgender Fehler abgefangen:

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

Mein aktueller Beispielcode lautet:

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

Wie kann ich node.js dazu bringen, das Äquivalent von "--no-check-certificate" auszuführen?

Geuis
quelle

Antworten:

600

Günstige und unsichere Antwort:

Hinzufügen

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

im Code, bevor Sie anrufen https.request()

In dieser Frage wird ein sicherer Weg beantwortet (die obige Lösung macht den gesamten Knotenprozess unsicher)

Juanra
quelle
2
Arbeitete wie ein Zauber für mich! Ich habe diesen Code direkt platziert, nachdem ich alles ganz oben in meine Hauptanwendung js aufgenommen habe.
Xedecimal
Dies funktionierte auch für die Kombination NodeJS & SailJS. Ich habe es oben auf local.js hinzugefügt
Michael Kork.
38
Verwenden Sie diese Option oder "RejectUnauthorized" nicht in einer Produktionsumgebung, da hierdurch alle Arten von Sicherheitsüberprüfungen deaktiviert werden.
Jason Walton
3
Ich hatte Probleme beim Ausführen von Tests mit Mokka auf meinem selbstsignierten https-Knotenserver und beim Hinzufügen dieses Tests unmittelbar bevor Beschreibungsblöcke meine Tests bestanden haben.
Artis3n
Dies ist wahrscheinlich nicht der sicherste Weg, um das Problem zu beheben. Siehe stackoverflow.com/questions/20433287/…
Matt Pennington
166

Versuchen Sie, in Ihre Anforderungsoptionen Folgendes aufzunehmen:

   var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      method: 'GET',
      rejectUnauthorized: false,
      requestCert: true,
      agent: false
    },
Meg Sharkey
quelle
Hat für mich gearbeitet. Ich benutze Restler und sehe, dass es die Optionen nicht standardmäßig weitergeleitet hat, also musste ich es patchen.
Olivier Amblet
2
Damit dies funktioniert, müssen Sie eine explizite Instanz eines benutzerdefinierten Agenten bereitstellen. Erstellen Sie das Optionsobjekt und legen Sie den Agenten fest: 'options.agent = new https.Agent (options);' Dann rufen Sie einfach 'https.request (options)' an
Max
14
Nun, das funktionierte für mich nur mit der rejectUnauthorizedOption und sonst nichts
mcont
@mcont ich bestätige gerade rejectUnauthorizedwar gut genug alles andere ootb. Verwendung innerhalb der vs Code-Erweiterung. Besser noch PEM-Konfiguration zulassen, das mache ich als nächstes ...
Escape-llc
61

Glauben Sie nicht all denen, die versuchen, Sie in die Irre zu führen.

Fügen Sie in Ihrer Anfrage einfach Folgendes hinzu:

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

Wenn Sie nicht autorisierte Zertifikate aktivieren, sind Sie überhaupt nicht geschützt (MITM ausgesetzt, weil die Identität nicht überprüft wurde), und das Arbeiten ohne SSL ist kein großer Unterschied. Die Lösung besteht darin, das erwartete CA-Zertifikat anzugeben, wie im nächsten Snippet gezeigt. Stellen Sie sicher, dass der allgemeine Name des Zertifikats mit der Adresse identisch ist, die Sie in der Anforderung angerufen haben (wie im Host angegeben):

Was Sie dann bekommen, ist:

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

Bitte lesen Sie diesen Artikel (Offenlegung: Blog-Beitrag des Autors dieser Antwort) hier, um zu verstehen:

  • Funktionsweise von CA-Zertifikaten
  • So generieren Sie CA-Zertifikate zum einfachen Testen, um die Produktionsumgebung zu simulieren
Hesham Yassin
quelle
7
Dies funktioniert und ist der richtige Weg, um das Problem "Fehler: Selbstsigniertes Zertifikat in der Zertifikatkette" zu beheben.
RohanRasane
1
Warum setzen Sie fs.readFileSync in Klammern, anstatt es als Zeichenfolge zu speichern?
Lelo
Lelo: Klammern verwandeln es in ein Array. ca: erwartet eine Reihe von Zertifikaten. Diese Datei sollte eine durch Kommas getrennte Liste von Zertifikaten sein. Oft verwenden Benutzer eine innere Funktion, um eine PEM-Datei in ein Array umzuwandeln. Für ein selbstsigniertes CET sollte ein einzelnes Zertifikat funktionieren.
John David
53

Fügen Sie die folgende Umgebungsvariable hinzu:

NODE_TLS_REJECT_UNAUTHORIZED=0

zB mit export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(Mit großem Dank an Juanra)

Armand
quelle
Dies funktionierte für mich beim Versuch zu rennenwebdriver-manager update
Ashley
3
setze NODE_TLS_REJECT_UNAUTHORIZED = 0 für Windows
Felipe SS
Dies war eine großartige Lösung für meine Entwicklungsumgebung
David
14

Hinzufügen zu @Armand Antwort:

Fügen Sie die folgende Umgebungsvariable hinzu:

NODE_TLS_REJECT_UNAUTHORIZED = 0 zB beim Export:

export NODE_TLS_REJECT_UNAUTHORIZED = 0 (mit großem Dank an Juanra)

Wenn Sie unter Windows verwenden:

set NODE_TLS_REJECT_UNAUTHORIZED=0

Danke an: @ weagle08

IamStalker
quelle
12

Sie können auch eine Anforderungsinstanz mit Standardoptionen erstellen:

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

Für meteorJS können Sie mit npmRequestOptions festlegen.

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
quelle
1

Oder Sie können versuchen, die lokale Namensauflösung ( hostsDatei im Verzeichnis der etcmeisten Betriebssysteme, Details unterscheiden sich) wie folgt hinzuzufügen :

192.168.1.1 Linksys 

und als nächstes

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

wird funktionieren.

piaf
quelle
3
Es stimmt, dass dies die Frage beantworten könnte, aber ich denke, der nächste Fehler wird in diesem Fall DEPTH_ZERO_SELF_SIGNED_CERT sein.
Olivier Amblet
1
Wie kommt man also um DEPTH_ZERO_SELF_SIGNED_CERT herum? Darauf stoße ich jetzt.
Reza
3
@reza: Fügen Sie dies zu Ihren Optionen hinzu:rejectUnauthorized: false
Obay
1
Ich weiß, dass dies ein wenig alt ist, aber zum späteren Nachschlagen (um dies richtig zu machen) müssen Sie eine PEM-Codierung des selbstsignierten Zertifikats erhalten und es als Zertifizierungsstelle in die Optionen aufnehmen (was Sie anscheinend auch benötigen) um den Agentenwert festzulegen, aber das kann falsch sein). Da das Zertifikat selbstsigniert ist, fungiert es als eigene Zertifizierungsstelle und kann daher zur Selbstverifizierung verwendet werden. Ich würde jedoch auch fragen, ob es sich wirklich lohnt, dies auf einem Router zu tun, da die Firmware wahrscheinlich heruntergeladen werden könnte und daher der private Schlüssel leicht kompromittiert werden könnte.
Jonathan Gray