Zignorować nieprawidłowy samopodpisany certyfikat ssl w node.js przy pomocy https.request?

308

Pracuję nad małą aplikacją, która loguje się do mojego lokalnego routera bezprzewodowego (Linksys), ale mam problem z samopodpisanym certyfikatem ssl routera.

Uruchomiłem wget 192.168.1.1 i otrzymałem:

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

W węźle wychwytywany błąd to:

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

Mój obecny przykładowy kod to:

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

Jak mogę uzyskać polecenie, aby node.js zrobił odpowiednik „--no-check-certificate”?

Geuis
źródło

Odpowiedzi:

599

Tania i niepewna odpowiedź:

Dodaj

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

w kodzie, przed wywołaniem https.request()

Bardziej bezpieczny sposób (powyższe rozwiązanie powoduje, że proces całego węzła jest niepewny) odpowiada na to pytanie

Juanra
źródło
2
Dla mnie zadziałało jak urok! Umieściłem ten kod zaraz po tym, jak włączyłem wszystko na samą górę mojej głównej aplikacji js.
Xedecimal
Działa to również w kombinacji NodeJS i SailJS. Dodałem go na początku pliku local.js
Michael Kork.
38
Nie używaj tego lub „odrzucaj nieautoryzowane” w środowisku produkcyjnym, ponieważ wyłącza to wszelkiego rodzaju kontrole bezpieczeństwa.
Jason Walton
3
Miałem problem z uruchomieniem testów przy użyciu mokki na moim samopodpisanym serwerze węzła https i dodanie tego bezpośrednio przed blokami opisowymi spowodowało, że moje testy przeszły pomyślnie.
artis3n
To prawdopodobnie nie jest najbezpieczniejszy sposób rozwiązania problemu. Zobacz stackoverflow.com/questions/20433287/…
Matt Pennington
166

W opcjach żądania spróbuj uwzględnić następujące elementy:

   var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      method: 'GET',
      rejectUnauthorized: false,
      requestCert: true,
      agent: false
    },
Meg Sharkey
źródło
Pracował dla mnie. Używam Restlera i widzę, że domyślnie nie przekazał opcji, więc musiałem go załatać.
Olivier Amblet
2
Aby to zadziałało, musisz podać jawną instancję niestandardowego agenta. Utwórz obiekt opcji i ustaw agenta: „options.agent = nowy https.Agent (opcje);” Następnie wystarczy wywołać „https.request (opcje)”
maks.
14
Cóż, to zadziałało dla mnie tylko z rejectUnauthorizedopcją i niczym innym
mcont
@mcont potwierdzam, że rejectUnauthorizedbył wystarczająco dobry wszystko inne ootb. Używanie rozszerzenia w ramach vs. Lepiej jeszcze pozwól na konfigurację PEM, zrobię to później ...
escape-llc
61

Nie wierz wszystkim, którzy próbują cię zwieść.

W swoim żądaniu wystarczy dodać:

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

Jeśli włączysz nieautoryzowane certyfikaty, w ogóle nie będziesz chroniony (narażony na działanie MITM z powodu nie sprawdzania tożsamości), a praca bez SSL nie będzie dużą różnicą. Rozwiązaniem jest określenie oczekiwanego certyfikatu urzędu certyfikacji, jak pokazano w następnym fragmencie. Upewnij się, że nazwa pospolita certyfikatu jest identyczna z adresem podanym w żądaniu (jak określono w hoście):

Otrzymasz wtedy:

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

Przeczytaj ten artykuł (ujawnienie: post na blogu napisany przez autora tej odpowiedzi), aby zrozumieć:

  • Jak działają certyfikaty CA
  • Jak generować certyfikaty CA do łatwego testowania w celu symulacji środowiska produkcyjnego
Hesham Yassin
źródło
7
To działa i jest właściwym sposobem na rozwiązanie problemu „Błąd: samopodpisany certyfikat w łańcuchu certyfikatów”.
RohanRasane
1
dlaczego wstawiasz fs.readFileSync w nawiasach zamiast przechowywać je jako ciąg?
Lelo
Lelo: nawiasy zamieniają go w tablicę. ca: oczekuje szeregu certyfikatów. Ten plik powinien być listą certyfikatów oddzielonych przecinkami, często ludzie używają funkcji wewnętrznej, aby zmienić plik PEM w tablicę. W przypadku samopodpisanego cet pojedynczy certyfikat „powinien” działać.
JohnDavid
53

Dodaj następującą zmienną środowiskową:

NODE_TLS_REJECT_UNAUTHORIZED=0

np. z export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(wielkie dzięki dla Juanry)

Armand
źródło
To działało dla mnie, gdy próbowałem uciecwebdriver-manager update
Ashley
3
ustaw NODE_TLS_REJECT_UNAUTHORIZED = 0 dla systemu Windows
Felipe SS
To było świetne rozwiązanie dla mojego środowiska programistycznego
David
14

Dodanie do odpowiedzi na @Armand:

Dodaj następującą zmienną środowiskową:

NODE_TLS_REJECT_UNAUTHORIZED = 0 np. Z eksportem:

eksport NODE_TLS_REJECT_UNAUTHORIZED = 0 (wielkie podziękowania dla Juanry)

Jeśli korzystasz z systemu Windows:

set NODE_TLS_REJECT_UNAUTHORIZED=0

Dzięki: @ weagle08

IamStalker
źródło
12

Możesz także utworzyć instancję żądania z domyślnymi opcjami:

require('request').defaults({ rejectUnauthorized: false })
Eduardo
źródło
3

W przypadku MeteJS możesz ustawić za pomocą 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
źródło
1

Możesz też spróbować dodać w lokalnej rozpoznawaniu nazw ( hostsplik znaleziony w katalogu etcw większości systemów operacyjnych, szczegóły różnią się) coś takiego:

192.168.1.1 Linksys 

i dalej

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

będzie działać.

piaf
źródło
3
prawda, że ​​może to odpowiedzieć na pytanie, ale myślę, że następnym błędem będzie w tym przypadku DEPTH_ZERO_SELF_SIGNED_CERT.
Olivier Amblet
1
więc jak można obejść DEPTH_ZERO_SELF_SIGNED_CERT? Teraz na to wpadam.
reza
3
@reza: dodaj to do swoich opcji:rejectUnauthorized: false
Obay
1
Wiem, że jest to trochę stare, ale do wykorzystania w przyszłości (aby zrobić to we właściwy sposób), musisz uzyskać kodowanie PEM samopodpisanego certyfikatu i uwzględnić go w opcjach jako urząd certyfikacji (najwyraźniej potrzebujesz również aby ustawić wartość agenta, ale może to być fałsz). Ponieważ certyfikat jest samopodpisany, działa jak własny urząd certyfikacji i dlatego można go użyć do weryfikacji. Chciałbym jednak zapytać, czy naprawdę warto byłoby zrobić to na routerze, ponieważ oprogramowanie można prawdopodobnie pobrać, a zatem klucz prywatny można łatwo złamać.
Jonathan Gray,