如何为 HTTPS Node.js 服务器使用自签名证书?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19665863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use a self signed certificate for a HTTPS Node.js server?
提问by Brett
I have started writing a wrapper for an API which requires all requests to be over HTTPS. Instead of making requests to the actual API while I am developing and testing it I would like to run my own server locally which mocks the responses.
我已经开始为一个 API 编写一个包装器,它要求所有请求都通过 HTTPS。我不想在开发和测试实际 API 时向它发出请求,而是想在本地运行我自己的服务器来模拟响应。
I am confused about how to generate the certificates I need to create a HTTPS server and send requests to it.
我对如何生成创建 HTTPS 服务器并向其发送请求所需的证书感到困惑。
My server looks something like this:
我的服务器看起来像这样:
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);
The pem files were generated with:
pem 文件是通过以下方式生成的:
openssl genrsa 1024 > key.pem
openssl req -x509 -new -key key.pem > cert.pem
And a request looks something like this:
一个请求看起来像这样:
var options = {
host: 'localhost',
port: 8000,
path: '/api/v1/test'
};
https.request(options, function(res) {
res.pipe(process.stdout);
}).end();
With this setup I get Error: DEPTH_ZERO_SELF_SIGNED_CERT, so I think I need to add a caoption for the request.
有了这个设置,我得到了Error: DEPTH_ZERO_SELF_SIGNED_CERT,所以我想我需要ca为请求添加一个选项。
So my question is how should I generate the following:
所以我的问题是我应该如何生成以下内容:
- The server
key? - The server
cert? - The
cafor the request?
- 服务器
key? - 服务器
cert? - 在
ca为请求?
I have read a few things about generating self signed certificates with openssl, but can't seem to wrap my head around it and figure out which keys and certificates to use where in my node code.
我已经阅读了一些关于使用 openssl 生成自签名证书的内容,但似乎无法理解它并找出在我的节点代码中使用哪些密钥和证书。
Update
更新
The API provides a CA certificate to use instead of the defaults. The following code works using their certificate and this is what I want to reproduce locally.
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();
回答by CoolAJ86
Update (Nov 2018): Do you needself-signed certs?
更新(2018 年 11 月):您需要自签名证书吗?
Or would real certificates get the job done better? Have you considered any of these?
或者真正的证书会让工作做得更好?你考虑过这些吗?
- Let's Encrypt via Greenlock.js
- Let's Encrypt via https://greenlock.domains
- Localhost relay service such as https://telebit.cloud
- 让我们通过Greenlock.js加密
- 让我们通过https://greenlock.domains加密
- 本地主机中继服务,例如https://telebit.cloud
(Note: Let's Encrypt can also issue certificates to private networks)
(注:Let's Encrypt 也可以向私有网络颁发证书)
ScreenCast
投屏
https://coolaj86.com/articles/how-to-create-a-csr-for-https-tls-ssl-rsa-pems/
https://coolaj86.com/articles/how-to-create-a-csr-for-https-tls-ssl-rsa-pems/
Full, Working example
完整的工作示例
- creates certificates
- runs node.js server
- no warnings or errors in node.js client
- no warnings or errors in cURL
- 创建证书
- 运行 node.js 服务器
- node.js 客户端中没有警告或错误
- cURL 中没有警告或错误
https://github.com/coolaj86/nodejs-self-signed-certificate-example
https://github.com/coolaj86/nodejs-self-signed-certificate-example
Using localhost.greenlock.domainsas an example (it points to 127.0.0.1):
使用localhost.greenlock.domains作为一个例子(它指向127.0.0.1):
server.js
服务器.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 = {
// this is ONLY the PRIVATE KEY
key: fs.readFileSync(path.join(__dirname, 'server', 'privkey.pem'))
// You DO NOT specify `ca`, that's only for peer authentication
//, ca: [ fs.readFileSync(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))]
// This should contain both cert.pem AND chain.pem (in that order)
, 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.greenlock.domains:' + port);
});
client.js
客户端.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.greenlock.domains'
;
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();
And the script that makes the certificate files:
以及制作证书文件的脚本:
make-certs.sh
make-certs.sh
#!/bin/bash
FQDN=
# 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
For example:
例如:
bash make-certs.sh 'localhost.greenlock.domains'
Hopefully this puts the nail in the coffin on this one.
希望这能把钉子钉在棺材上。
And some more explanation: https://github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js
还有一些解释:https: //github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js
Install private cert on iOS Mobile Safari
在 iOS Mobile Safari 上安装私有证书
You need to create a copy of the root ca certificate a DER format with a .crt extension:
您需要创建一个带有 .crt 扩展名的 DER 格式的根 ca 证书的副本:
# 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
Then you can simply serve that file with your webserver. When you click the link you should be asked if you want to install the certificate.
然后您可以简单地使用您的网络服务器提供该文件。当您单击该链接时,系统会询问您是否要安装证书。
For an example of how this works you can try installing MIT's Certificate Authority: https://ca.mit.edu/mitca.crt
有关其工作原理的示例,您可以尝试安装 MIT 的证书颁发机构:https: //ca.mit.edu/mitca.crt
Related Examples
相关例子
- https://github.com/coolaj86/nodejs-ssl-example
- https://github.com/coolaj86/nodejs-ssl-trusted-peer-example
- https://github.com/coolaj86/node-ssl-root-cas
- https://github.com/coolaj86/nodejs-https-sni-vhost-example
- (Multiple vhosts with SSL on the same server)
- https://telebit.cloud
- (get REAL SSL certs you can use TODAY for testing on localhost)
- https://github.com/coolaj86/nodejs-ssl-example
- https://github.com/coolaj86/nodejs-ssl-trusted-peer-example
- https://github.com/coolaj86/node-ssl-root-cas
- https://github.com/coolaj86/nodejs-https-sni-vhost-example
- (在同一台服务器上使用 SSL 的多个虚拟主机)
- https://telebit.cloud
- (获取真正的 SSL 证书,您可以在今天使用它在本地主机上进行测试)
回答by Loourr
Try adding this to your request options
尝试将此添加到您的请求选项中
var options = {
host: 'localhost',
port: 8000,
path: '/api/v1/test',
// These next three lines
rejectUnauthorized: false,
requestCert: true,
agent: false
};
回答by user1570577
Try adding
尝试添加
agent: false,
rejectUnauthorized: false
回答by binderbound
Your key generation looks okay. You shouldn't need a ca because you aren't rejecting unsigned requests.
您的密钥生成看起来不错。您不应该需要 ca,因为您不会拒绝未签名的请求。
Add .toString() to the end of your readFileSync methods so that you are actually passing a string, not a file object.
将 .toString() 添加到 readFileSync 方法的末尾,以便您实际上传递的是字符串,而不是文件对象。
回答by John Slegers
This procedure allows you to create both a certificate authority & a certificate :
此过程允许您创建证书颁发机构和证书:
grab this
ca.cnffile to use as a configuration shortcut :wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/ca.cnf
获取此
ca.cnf文件以用作配置快捷方式:wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/ca.cnf
create a new certificate authority using this configuration :
openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-cert.pem
使用此配置创建一个新的证书颁发机构:
openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-cert.pem
now that we have our certificate authority in
ca-key.pemandca-cert.pem, let's generate a private key for the server :openssl genrsa -out key.pem 4096
现在我们在
ca-key.pemand 中拥有我们的证书颁发机构ca-cert.pem,让我们为服务器生成一个私钥:openssl genrsa -out key.pem 4096
grab this
server.cnffile to use as a configuration shortcut :wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/server.cnf
获取此
server.cnf文件以用作配置快捷方式:wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/server.cnf
generate the certificate signing request using this configuration :
openssl req -new -config server.cnf -key key.pem -out csr.pem
使用此配置生成证书签名请求:
openssl req -new -config server.cnf -key key.pem -out csr.pem
sign the request :
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
签署请求:
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
I found this procedure here, along with more information on how to use these certificates.
我在这里找到了这个过程,以及关于如何使用这些证书的更多信息。

