@kirick

Как исправить работу StartSSL сертификата в Node.js v4.1.0?

Решил давеча обновиться с Node.js v0.12.7 на Node.js v4.1.0. После обновления проблема — при запросе к серверу через curl (из командной строки) этот самый curl отказывается делать запрос с ошибкой:

* About to connect() to test.monopoly-one.com port 443 (#0)
* Trying 51.254.61.44... connected
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.

Этот же запрос curl с ключом `-k`:

* About to connect() to test.monopoly-one.com port 443 (#0)
* Trying 51.254.61.44... connected
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=RU; CN=test.monopoly-one.com; emailAddress=webmaster@monopoly-one.com
* start date: 2015-06-28 08:38:09 GMT
* expire date: 2016-06-28 18:38:55 GMT
* issuer: C=IL; O=StartCom Ltd.; OU=Secure Digital Certificate Signing; CN=StartCom Class 1 Primary Intermediate Server CA
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.

При этом, если откатиться на Node.js v0.12.7, то абсолютно такой же серверный код с абсолютно теми же сертификатом и ключом не вызывает у curl на том же самом устройстве никакого дискомфорта:

* About to connect() to test.monopoly-one.com port 443 (#0)
* Trying 51.254.61.44... connected
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* subject: C=RU; CN=test.monopoly-one.com; emailAddress=webmaster@monopoly-one.com
* start date: 2015-06-28 08:38:09 GMT
* expire date: 2016-06-28 18:38:55 GMT
* issuer: C=IL; O=StartCom Ltd.; OU=Secure Digital Certificate Signing; CN=StartCom Class 1 Primary Intermediate Server CA
* SSL certificate verify ok.

То есть проблема явно не в том, где выполняется curl, а именно в версии Node.js, однако я никак не смог найти в сети чейнджлог, который внятно описывает, что в Node.js поменялось в плане создания https сервера.

Кусочек кода, который создаёт https сервер:
var __fs = require('fs'),
    __https = require('https');
self.__server = __https.createServer({
    cert: __fs.readFileSync('/valid/path/to.crt'),
    key: __fs.readFileSync('/valid/path/to_decrypted.key')
}, self.preparer);
self.__server.addContext('test.monopoly-one.com', {
    cert: __fs.readFileSync('/valid/path/to.crt'),
    key:  __fs.readFileSync('/valid/path/to_decrypted.key'),
    ca: [
        __fs.readFileSync('/valid/path/to/startssl/ca.pem')
        __fs.readFileSync('/valid/path/to/startssl/sub.class1.server.ca.pem')
    ]
});
self.__server.listen(443);

Та же версия, но с использованием tls.createSecureContext() и SNICallback вместо self.__server.addContext ведёт себя абсолютно так же.

UPD: забыл упомянуть, что все современные браузеры ведут себя абсолютно одинаково и не выказывают беспокойств.

UPD 2: изменение порядка chiphers помогает заставить curl сменить ECDHE-RSA-AES256-GCM-SHA384 на ECDHE-RSA-AES128-GCM-SHA256 (как раньше), но сертификату он по-прежнему не доверяет.
  • Вопрос задан
  • 1060 просмотров
Решения вопроса 1
@kirick Автор вопроса
Решение нашлось — теперь контент файлов из массива ca надо не отправлять в Node.JS, а прописывать прямо в .crt файл, создавая цепочку. То есть файл /valid/path/to.crt должен содержать сам сертификат, потом в нём же должен идти промежуточный сертификат и корневой. И тогда всё работает.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@banifaciy
Все верно, обратите внимание на cipher.
В первом случае используется * SSL connection using ECDHE-RSA-AES128-GCM-SHA256
Во втором случае используется * SSL connection using ECDHE-RSA-AES256-GCM-SHA384

Проблема в том, что ребята изменили дефолтовый cipher. О чем упомянули в чейнджлоге: https://github.com/nodejs/node/blob/v4.1.1/CHANGEL...

Ваша проблема решается установкой параметра ciphers в опциях, при создании сервера https.createServer
ciphers: A string describing the ciphers to use or exclude, separated by :


Более подробно можете посмотреть тут: https://github.com/nodejs/node/pull/826
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы