Игнорировать недействительный самоподписанный ssl-сертификат в node.js с помощью https.request?

309

Я работаю над небольшим приложением, которое подключается к моему локальному беспроводному маршрутизатору (Linksys), но у меня проблема с самозаверяющим ssl-сертификатом маршрутизатора.

Я запустил wget 192.168.1.1 и получил:

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

В узле обнаруживается ошибка:

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

Мой текущий пример кода:

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

Как я могу получить файл node.js, эквивалентный «--no-check-Certificate»?

Geuis
источник

Ответы:

601

Дешевый и небезопасный ответ:

Добавить

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

в коде, перед звонком https.request()

Более безопасный способ (решение выше делает весь процесс узла незащищенным) дает ответ на этот вопрос

Juanra
источник
2
Работал как шарм для меня! Я поместил этот код сразу после того, как включил все в самый верх моего основного приложения js.
Шестнадцатое
Это также работает для комбо NodeJS & SailJS. Я добавил его в начало local.js
Майкл Корк.
38
Не используйте это или «rejectUnauthorized» в производственной среде, так как это отключает все виды проверок безопасности.
Джейсон Уолтон
3
У меня были проблемы с запуском тестов с использованием mocha на моем самозаверяющем сервере узлов https и добавлением этого непосредственно перед тем, как какие-либо блоки описаний сделали мои тесты успешными.
artis3n
Вероятно, это не самый безопасный способ решения проблемы. См. Stackoverflow.com/questions/20433287/…
Мэтт Пеннингтон
166

В опциях вашего запроса попробуйте включить следующее:

   var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      method: 'GET',
      rejectUnauthorized: false,
      requestCert: true,
      agent: false
    },
Мег Шарки
источник
Работал на меня. Я использую рестлер и вижу, что по умолчанию параметры не пересылаются, поэтому мне пришлось его исправлять.
Оливье Эмблет
2
Чтобы это работало, вам нужно предоставить явный экземпляр пользовательского агента. Создайте объект параметров и установите агента: 'options.agent = новый https.Agent (параметры);' Тогда просто позвоните «https.request (варианты)»
Макс
14
Ну, это сработало для меня только с rejectUnauthorizedопцией и ничем иным
mcont
@ mcont Я подтверждаю, что все rejectUnauthorizedбыло достаточно хорошо, ootb. Использование внутри расширения против кода. Еще лучше разрешить настройку PEM, я сделаю это дальше ...
escape-llc
61

Не верьте всем тем, кто пытается ввести вас в заблуждение.

В вашем запросе просто добавьте:

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

Если вы включите неавторизованные сертификаты, вы вообще не будете защищены (выставлены MITM для проверки личности), и работа без SSL не будет большой разницей. Решение состоит в том, чтобы указать сертификат CA, который вы ожидаете, как показано в следующем фрагменте. Убедитесь, что общее имя сертификата совпадает с адресом, который вы назвали в запросе (как указано в хосте):

Тогда вы получите:

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

Пожалуйста, прочитайте эту статью (раскрытие: сообщение в блоге, написанное автором этого ответа) здесь, чтобы понять:

  • Как работают сертификаты CA
  • Как легко генерировать сертификаты CA для тестирования, чтобы имитировать производственную среду
Хешам Ясин
источник
7
Это работает и является правильным способом решения проблемы «Ошибка: самозаверяющий сертификат в цепочке сертификатов».
RohanRasane
1
почему вы помещаете fs.readFileSync в скобки, а не храните его в виде строки?
Лело
Лело: скобки превращают его в массив. CA: ожидает массив сертификатов. Этот файл должен представлять собой список сертификатов через запятую, часто люди используют внутреннюю функцию, чтобы превратить файл PEM в массив. Для самозаверяющего cet один сертификат "должен" работать.
JohnDavid
53

Добавьте следующую переменную среды:

NODE_TLS_REJECT_UNAUTHORIZED=0

например с export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(с огромной благодарностью Хуанре)

Armand
источник
Это сработало для меня при попытке бежатьwebdriver-manager update
Эшли
3
установить NODE_TLS_REJECT_UNAUTHORIZED = 0 для окон
Фелипе С.С.
Это было отличное решение для моей среды разработки
Дэвид
14

Добавление к ответу @Armand:

Добавьте следующую переменную среды:

NODE_TLS_REJECT_UNAUTHORIZED = 0, например, с экспортом:

export NODE_TLS_REJECT_UNAUTHORIZED = 0 (с большой благодарностью Хуанре)

Если вы используете Windows:

set NODE_TLS_REJECT_UNAUTHORIZED=0

Благодаря: @ weagle08

IamStalker
источник
12

Вы также можете создать экземпляр запроса с параметрами по умолчанию:

require('request').defaults({ rejectUnauthorized: false })
Эдуардо
источник
3

Для meteorJS вы можете установить с помощью 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
источник
1

Или вы можете попробовать добавить в локальном разрешении имен ( hostsфайл, найденный в каталоге etcв большинстве операционных систем, детали отличаются) примерно так:

192.168.1.1 Linksys 

и следующий

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

буду работать.

Пиаф
источник
3
Это правда, что это может ответить на вопрос, но я думаю, что следующая ошибка будет DEPTH_ZERO_SELF_SIGNED_CERT в этом случае.
Оливье Эмблет
1
так как же обойти DEPTH_ZERO_SELF_SIGNED_CERT? Я сталкиваюсь с этим сейчас.
Реза
3
@reza: добавьте это к вашим опциям:rejectUnauthorized: false
Obay
1
Я знаю, что это немного устарело, но для дальнейшего использования (для того, чтобы сделать это правильно), вам нужно получить PEM-кодировку самоподписанного сертификата и включить его в параметры в качестве CA (вам, очевидно, также нужен установить значение агента, но это может быть ложным). Поскольку сертификат самоподписан, он действует как собственный ЦС и, следовательно, может использоваться для самопроверки. Однако я также хотел бы спросить, действительно ли это стоит делать на маршрутизаторе, поскольку микропрограммное обеспечение может быть загружено и, следовательно, закрытый ключ может быть легко взломан.
Джонатан Грей