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

Как использовать самоподписанный сертификат для сервера HTTPS Node.js?

Я начал писать обертку для API, которая требует, чтобы все запросы превышали HTTPS. Вместо того, чтобы делать запросы к фактическому API во время разработки и тестирования, я хотел бы запустить свой собственный локальный сервер, который издевается над ответами.

Я смущен тем, как создавать сертификаты, необходимые для создания HTTPS-сервера, и отправлять ему запросы.

Мой сервер выглядит примерно так:

var options = {
  key: fs.readFileSync('./key.pem'),
  cert: fs.readFileSync('./cert.pem')
};

https.createServer(options, function(req, res) {
  res.writeHead(200);
  res.end('OK\n');
}).listen(8000);

Файлы pem были сгенерированы с помощью:

openssl genrsa 1024 > key.pem
openssl req -x509 -new -key key.pem > cert.pem

И запрос выглядит примерно так:

var options = {
  host: 'localhost',
  port: 8000,
  path: '/api/v1/test'
};

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

С этой настройкой я получаю Error: DEPTH_ZERO_SELF_SIGNED_CERT, поэтому, думаю, мне нужно добавить параметр ca для запроса.

Итак, мой вопрос заключается в том, как мне создать следующее:

  • Сервер key?
  • Сервер cert?
  • ca для запроса?

Я прочитал несколько вещей о создании самоподписанных сертификатов с помощью openssl, но, похоже, не могу обернуть вокруг себя и выяснить, какие ключи и сертификаты использовать в моем коде node.

Обновление

API предоставляет сертификат CA для использования вместо значений по умолчанию. Следующий код работает с использованием своего сертификата, и это то, что я хочу воспроизвести локально.

var ca = fs.readFileSync('./certificate.pem');

var options = {
  host: 'example.com',
  path: '/api/v1/test',
  ca: ca
};
options.agent = new https.Agent(options);

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();
4b9b3361

Ответ 1

ScreenCast

https://coolaj86.com/articles/how-to-create-a-csr-for-https-tls-ssl-rsa-pems/

Полный, рабочий пример

  • создает сертификаты
  • запускает node.js сервер
  • никаких предупреждений или ошибок в node.js-клиенте
  • никаких предупреждений или ошибок в cURL

https://github.com/coolaj86/nodejs-self-signed-certificate-example

Используя localhost.daplie.com в качестве примера (он указывает на 127.0.0.1):

server.js

'use strict';

var https = require('https')
  , port = process.argv[2] || 8043
  , fs = require('fs')
  , path = require('path')
  , server
  , options
  ;

require('ssl-root-cas')
  .inject()
  .addFile(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))
  ;

options = {
  key: fs.readFileSync(path.join(__dirname, 'server', 'privkey.pem'))
// You don't need to specify `ca`, it done by `ssl-root-cas`
//, ca: [ fs.readFileSync(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))]
, cert: fs.readFileSync(path.join(__dirname, 'server', 'fullchain.pem'))
};


function app(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, encrypted world!');
}

server = https.createServer(options, app).listen(port, function () {
  port = server.address().port;
  console.log('Listening on https://127.0.0.1:' + port);
  console.log('Listening on https://' + server.address().address + ':' + port);
  console.log('Listening on https://localhost.daplie.com:' + port);
});

client.js

'use strict';

var https = require('https')
  , fs = require('fs')
  , path = require('path')
  , ca = fs.readFileSync(path.join(__dirname, 'client', 'my-private-root-ca.cert.pem'))
  , port = process.argv[2] || 8043
  , hostname = process.argv[3] || 'localhost.daplie.com'
  ;

var options = {
  host: hostname
, port: port
, path: '/'
, ca: ca
};
options.agent = new https.Agent(options);

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

И script, который делает файлы сертификата:

make-certs.sh

#!/bin/bash
FQDN=$1

# make directories to work from
mkdir -p server/ client/ all/

# Create your very own Root Certificate Authority
openssl genrsa \
  -out all/my-private-root-ca.privkey.pem \
  2048

# Self-sign your Root Certificate Authority
# Since this is private, the details can be as bogus as you like
openssl req \
  -x509 \
  -new \
  -nodes \
  -key all/my-private-root-ca.privkey.pem \
  -days 1024 \
  -out all/my-private-root-ca.cert.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com"

# Create a Device Certificate for each domain,
# such as example.com, *.example.com, awesome.example.com
# NOTE: You MUST match CN to the domain name or ip address you want to use
openssl genrsa \
  -out all/privkey.pem \
  2048

# Create a request from your Device, which your Root CA will sign
openssl req -new \
  -key all/privkey.pem \
  -out all/csr.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Tech Inc/CN=${FQDN}"

# Sign the request from Device with your Root CA
openssl x509 \
  -req -in all/csr.pem \
  -CA all/my-private-root-ca.cert.pem \
  -CAkey all/my-private-root-ca.privkey.pem \
  -CAcreateserial \
  -out all/cert.pem \
  -days 500

# Put things in their proper place
rsync -a all/{privkey,cert}.pem server/
cat all/cert.pem > server/fullchain.pem         # we have no intermediates in this case
rsync -a all/my-private-root-ca.cert.pem server/
rsync -a all/my-private-root-ca.cert.pem client/

# create DER format crt for iOS Mobile Safari, etc
openssl x509 -outform der -in all/my-private-root-ca.cert.pem -out client/my-private-root-ca.crt

Например:

bash make-certs.sh 'localhost.daplie.com'

Надеюсь, это наложит гвоздь в гроб на этом.

И еще несколько объяснений: https://github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js

Установить закрытый сертификат на iOS Mobile Safari

Вам необходимо создать копию корневого сертификата CA DER формата с расширением .crt:

# create DER format crt for iOS Mobile Safari, etc
openssl x509 -outform der -in all/my-private-root-ca.cert.pem -out client/my-private-root-ca.crt

Затем вы можете просто обслуживать этот файл на своем веб-сервере. Когда вы нажимаете на ссылку, вас спрашивают, хотите ли вы установить сертификат.

Пример того, как это работает, вы можете попробовать установить MIT Certificate Authority: https://ca.mit.edu/mitca.crt

Связанные примеры

Ответ 2

Попробуйте добавить это в свои параметры запроса

var options = {
  host: 'localhost',
  port: 8000,
  path: '/api/v1/test',
  // These next three lines
  rejectUnauthorized: false,
  requestCert: true,
  agent: false
};

Ответ 3

Ваше поколение ключей выглядит нормально. Вам не нужно использовать ca, потому что вы не отклоняете неподписанные запросы.

Добавьте .toString() в конец ваших методов readFileSync, чтобы вы фактически передавали строку, а не файл.

Ответ 4

Попробуйте добавить агент: false, rejectUnauthorized: false

Ответ 5

Эта процедура позволяет создать как центр сертификации, так и сертификат:

  • захватить этот ca.cnf файл для использования в качестве ярлыка конфигурации:

    wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/ca.cnf


  1. создайте новый центр сертификации, используя эту конфигурацию:

    openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-cert.pem


    1. теперь, когда у нас есть наш центр сертификации в ca-key.pem и ca-cert.pem, дайте сгенерировать закрытый ключ для сервера:

      openssl genrsa -out key.pem 4096


      1. захватить этот server.cnf файл для использования в качестве ярлыка конфигурации:

        wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/server.cnf


        1. сгенерируйте запрос на подпись сертификата с помощью этой конфигурации:

          openssl req -new -config server.cnf -key key.pem -out csr.pem


          1. Подпишите запрос:

            openssl x509 -req -extfile server.cnf -days 999 -passin "pass:password" -in csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem

Я нашел эту процедуру здесь, а также дополнительную информацию о том, как использовать эти сертификаты.