【发布时间】:2021-10-24 00:27:27
【问题描述】:
所以,在绝望的道路上,我想知道是否有人在某个地方可以帮助我配置 nodejs 以接受根 CA 自签名。我需要它才能通过带有 TLS 的 node-fetch 访问开发中的自定义 API。
环境
- 操作系统:Ubuntu 20.04 作为虚拟机中的来宾。 Windows 10 主机。
- Nodejs v15.12.0
- Apache2.4 服务器
我正在开发的 API 是一个 PHP 脚本,它允许我的 nodejs 后端查询一些数据。
自签名的根证书和 API 证书是使用 openssl 生成的,并且非常好,因为我可以使用 HTTPS 从浏览器中毫无问题地查询 API。
错误
当尝试从 nodejs 后端查询 API 时,我收到此错误:
FetchError: request to https://myapi.dev.local failed, reason: self signed certificate
at ClientRequest.<anonymous> (./node_modules/node-fetch/lib/index.js:1461:11)
at ClientRequest.emit (node:events:369:20)
at TLSSocket.socketErrorListener (node:_http_client:462:9)
at TLSSocket.emit (node:events:369:20)
at emitErrorNT (node:internal/streams/destroy:188:8)
at emitErrorCloseNT (node:internal/streams/destroy:153:3)
at processTicksAndRejections (node:internal/process/task_queues:81:21)"
尝试失败
首先,我尝试使用 dpkg-reconfigure ca-certificates 在 ubuntu 上安装证书,但后来我发现 nodejs 使用的是硬编码列表。
因此,由于出于安全考虑,我不想使用 env 变量 NODE_TLS_REJECT_UNAUTHORIZED=0,因此我尝试使用 NODE_EXTRA_CA_CERTS=pathToMycert.pem en 变量,但它没有任何改变,我也找不到任何信息知道发生了什么。
在我的 nodejs 后端,如果我执行console.log(process.env.NODE_EXTRA_CA_CERTS),它会打印出正确的路径。
我尝试通过此检查将我的 CA 与 tls.rootCertificates 匹配:
const tls = require('tls');
const fs = require('fs');
const ca = await fs.readFileSync(process.env.NODE_EXTRA_CA_CERTS, 'utf8');
console.log(ca); //successfully print the CA, so it exists.
const inList = tls.rootCertificates.some( cert =>{
console.log('testing ca : \n',cert);
return cert == ca;
});
console.log(`CA is ${ !inList ? 'not' : '' } in rootCertificates list...`);
它打印“CA 不在 rootCertificates 列表中”。不足为奇。
所以,我尝试对 tls secureContext 进行猴子补丁以包含我的证书:
const tls = require('tls');
const fs = require('fs');
const origCreateSecureContext = tls.createSecureContext;
tls.createSecureContext = options => {
const context = origCreateSecureContext(options);
const list = (process.env.NODE_EXTRA_CA_CERTS || '').split(',');
list.forEach(extraCert => {
const pem = fs.readFileSync(extraCert, { encoding : 'utf8' }).replace(/\r\n/g, "\n");
const certs = pem.match(/-----BEGIN CERTIFICATE-----\n[\s\S]+?\n-----END CERTIFICATE-----/g);
if(!certs) throw new Error(
`SelfSignedCertSupport : Invalid extra certificate ${extraCert}`
);
certs.forEach(cert => context.context.addCACert(cert.trim()));
});
return context;
};
没用。
我尝试(在此问题之后:https://github.com/nodejs/node/issues/27079)这样做:
const tls = require('tls');
const fs = require('fs');
const additionalCerts = [];
const list = (process.env.NODE_EXTRA_CA_CERTS || '').split(',');
list.forEach(extraCert => {
const pem = fs.readFileSync(extraCert, { encoding : 'utf8' }).replace(/\r\n/g, "\n");
const certs = pem.match(/-----BEGIN CERTIFICATE-----\n[\s\S]+?\n-----END CERTIFICATE-----/g);
if(!certs) throw new Error(
`SelfSignedCertSupport : Invalid extra certificate ${extraCert}`
);
additionalCerts.push(...certs);
});
tls.rootCertificates = [
...tls.rootCertificates,
...additionalCerts
];
没有运气。
我做错了什么?
【问题讨论】:
-
(0) 你说得对,系统(ca-certificates)存储无关紧要(1)我不做奇怪的专业,我的 Ubuntu 20.04(带有标准 repos)只能找到 10.19,但是在 Windows
NODE_EXTRA_CA_CERTS上使用 14.15.5 进行测试对我有用,假设文件是好的,如果由 OpenSSL 创建并且没有修改,它应该是。你能检查openssl x509 -in file显示的证书没有错误吗? (2)tls.rootCertificates只给你一个内置列表的副本,而不是包含添加的实际 X509_STORE,并且修补它根本没有用处。 ... -
... (3) 阅读源代码我认为
addCACert也应该 工作,虽然你不需要 match+forEach (尽管它实际接受的单数名称一个序列,但会默默地忽略无效输入)并且您不需要删除 CR(或“评论”信息) -
感谢您的回答。
openssl x509 -in file打印的证书没有错误。我重新生成了所有证书并再次尝试。还是行不通。 2 -> 这就是我所怀疑的...... 3:我尝试添加证书而不计算/更改文件内容:不工作。我还尝试使用ca参数在获取级别添加 CA:总是相同的错误。我试试最新版本的node看看是不是v15.12.0的bug。
标签: node.js ssl ssl-certificate self-signed-certificate