Подтвердить что ты не робот

Node.js Имя хоста /IP не соответствует именам сертификатов

У меня есть код:

var r = require('request');
r({
  method: 'POST',
  url: 'https://api.dropbox.com'},
  function() { console.log(arguments)  } )

Когда я запускаю его на рабочем столе с Node 0.9.4, я получаю его в консоли:

{ '0': [Error: Hostname/IP doesn't match certificate altnames] }

Когда я запускаю его на нетбуке с Node 0.6.12, все работает без ошибок (ответ 302 - я думаю, что это правильно).

В вопросе Node.js имя хоста /IP не соответствует сертификатам altnames, Rojuinex пишет: "Да, проблема с браузером... извините". Что означает "проблема с браузером"?

UPD. Эта проблема была решена после откат на Node v0.8

4b9b3361

Ответ 1

Так как 0.9.2 (включая 0.10.x) node.js теперь проверяет сертификаты по умолчанию. Вот почему вы могли видеть, что он становится более строгим, когда вы обновляете прошлое node.js 0.8. (HT: https://github.com/mscdex/node-imap/issues/181#issuecomment-14781480)

Вы можете избежать этого с помощью параметра {rejectUnauthorized:false}, но это имеет серьезные последствия для безопасности. Все, что вы отправляете партнеру, по-прежнему будет зашифровано, но гораздо проще установить атаку "человек в середине", то есть ваши данные будут зашифрованы для однорангового узла, но сам сверстник не является сервером, который вы так считаете!

Было бы лучше сначала диагностировать, почему сертификат не авторизуется, и посмотреть, можно ли это исправить.

Ответ 2

Немного обновленный ответ (поскольку я столкнулся с этой проблемой в разных обстоятельствах.)

Когда вы подключаетесь к серверу с использованием SSL, первое, что делает сервер, - это сертификат, в котором говорится: "Я api.dropbox.com". У сертификата есть "субъект", и у субъекта есть "CN" (сокращение от "общего имени".) В сертификате также может быть одно или несколько "subjectAltNames". Когда node.js подключается к серверу, node.js извлекает этот сертификат, а затем проверяет, что имя домена, которое, по его мнению, связано с (api.dropbox.com), совпадает либо с объектом CN, либо с одним из имен altnames. Обратите внимание, что в node 0.10.x, если вы подключаетесь с использованием IP-адреса, IP-адрес должен находиться в файлах altnames - node.js не будет пытаться проверить IP-адрес на CN.

Установка флага rejectUnauthorized в значение false приведет к обходу этой проверки, но прежде всего, если сервер предоставляет вам разные учетные данные, чем вы ожидаете, происходит что-то подозрительное, а во-вторых, это также обходит другие проверки - это не очень хорошая идея, если вы подключаетесь через Интернет.

Если вы используете node >= 0.11.x, вы также можете указать функцию checkServerIdentity: function(host, cert) для модуля tls, который должен возвращать undefined, если вы хотите разрешить соединение и исключить исключение в противном случае (хотя я не знаю, будет ли request проксировать этот флаг через tls для вас.) Может быть удобно объявить такую ​​функцию и console.log(host, cert);, чтобы выяснить, что происходит.

Ответ 3

В случае, если вы используете пакет http-proxy, это происходит, когда ваш сервер использует HTTP (например, localhost), а целью является HTTPS. Чтобы решить эту проблему, установите для свойства changeOrigin значение true.

const proxy = httpProxy.createProxyServer();

proxy.web(req, res, {
  changeOrigin: true,
  target: https://example.com:3000,
});

Если ваш сервер HTTPS и целевой сервер HTTPS, вы должны включить SSL сертификат

httpProxy.createServer({
  ssl: {
    key: fs.readFileSync('valid-ssl-key.pem', 'utf8'),
    cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
  },
  target: 'https://example.com:3000',
  secure: true
}).listen(443);

Ответ 4

Я знаю, что это старо, НО для кого-то другого:

Удалите https://из имени хоста и добавьте вместо него порт 443.

{
  method: 'POST',
  hostname: 'api.dropbox.com',
  port: 443
}

Ответ 5

У меня была та же проблема, что и запрос модуля запроса на запрос POST из другого места, и это было потому, что я оставил свойство хоста в заголовке (я копировал заголовок из исходного запроса).

Ответ 6

Другой способ исправить это в других обстоятельствах - использовать NODE_TLS_REJECT_UNAUTHORIZED=0 в качестве переменной среды.

NODE_TLS_REJECT_UNAUTHORIZED=0 node server.js

Ответ 7

После проверки того, что сертификат выпущен известным центром сертификации (ЦС), будут проверены альтернативные имена субъектов или проверено общее имя, чтобы убедиться, что имя хоста совпадает. Это в функции checkServerIdentity. Если сертификат имеет альтернативные имена субъекта, а имя хоста не указано в списке, вы увидите сообщение об ошибке, описанное ниже:

Имя хоста /IP не совпадает с альтернативными именами сертификатов

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

var r = require('request');

var opts = {
    method: "POST",
    ca: fs.readFileSync("ca.cer")
};

r('https://api.dropbox.com', opts, function (error, response, body) {
    // do something
});

Это подтвердит, что сертификат выдан предоставленным центром сертификации, но проверка имени хоста все равно будет выполнена. Достаточно будет просто указать центр сертификации, если сертификат содержит имя хоста в альтернативных именах субъектов. Если это не так, и вы также хотите пропустить проверку имени хоста, вы можете передать функцию noop для checkServerIdentity

var r = require('request');

var opts = {
    method: "POST",
    ca: fs.readFileSync("ca.cer"),
    agentOptions: { checkServerIdentity: function() {} }
};

r('https://api.dropbox.com', opts, function (error, response, body) {
    // do something
});

Ответ 8

У нас нет этой проблемы, если мы тестируем наш клиентский запрос с адресом назначения localhost (host или hostname на node.js), а общее имя нашего сервера - CN = localhost в сертификате сервера. Но даже если мы изменим localhost на 127.0.0.1 или любой другой IP-адрес, мы получим ошибку Hostname/IP doesn't match certificate altnames на node.js или SSL handshake failed Hostname/IP doesn't match certificate altnames SSL handshake failed на QT.

У меня была та же проблема с моим сертификатом сервера по моему клиентскому запросу. Чтобы решить эту проблему в моем клиентском приложении node.js, мне нужно было поставить subjectAltName в моем server_extension со следующим значением:

[ server_extension ]
       .
       .
       .

subjectAltName          = @alt_names_server

[alt_names_server]
IP.1 = x.x.x.x

и затем я использую -extension когда создаю и подписываю сертификат.

пример:

В моем случае я сначала экспортирую файл конфигурации эмитента, потому что этот файл server_extension:

export OPENSSL_CONF=intermed-ca.cnf

поэтому я создаю и подписываю сертификат своего сервера:

openssl ca \
    -in server.req.pem \
    -out server.cert.pem \
    -extensions server_extension \
    -startdate 'date +%y%m%d000000Z -u -d -2day' \
    -enddate 'date +%y%m%d000000Z -u -d +2years+1day'   

Он отлично работает на клиентах на основе node.js с запросами https, но не работает с клиентами на основе QT QSsl, когда мы определяем sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyPeer), если только мы не используем QSslSocket::VerifyNone он не будет работать, Если мы используем VerifyNone оно заставит наше приложение не проверять сертификат однорангового VerifyNone поэтому оно примет любой сертификат. Таким образом, для ее решения мне нужно изменить общее имя моего сервера в его сертификате и заменить его значением на IP-адрес, на котором работает мой сервер.

например:

CN = 127.0.0.1