我使用CLI工具构建具有很酷上传功能的混合移动应用程序,因此我可以在设备上测试应用程序而无需通过应用程序商店(它的离子cli)。然而,在我的公司,像许多其他公司一样,TLS请求与公司自己的自定义CA证书重新签名,我在我的机器上有钥匙串(OS X)。但是,nodejs不使用密钥链来获取其信任的CA列表。我无法控制ionic-cli应用程序,因此我无法简单地将{ca:}属性传递给https模块。我还可以看到这是我无法控制的任何节点应用程序的问题。是否可以告诉nodejs信任CA?
我不确定这是属于信息安全还是任何其他交易所...
答案 0 :(得分:53)
Node.js 7.3.0(以及LTS版本6.10.0和4.8.0)添加了NODE_EXTRA_CA_CERTS
环境变量,供您传递CA证书文件。它比使用NODE_TLS_REJECT_UNAUTHORIZED
禁用证书验证更安全。
$ export NODE_EXTRA_CA_CERTS=[your CA certificate file path]
答案 1 :(得分:6)
我知道在控制应用程序时有两个npm模块可以解决这个问题:
node-ssl-root-cas
捆绑它自己的节点根CA副本,并且还可以将您自己的CA添加到信任中。它将证书放在https全局代理上,因此它仅用于https模块,而不是纯tls连接。此外,如果您使用自定义代理而不是全局代理,则需要执行额外的步骤。
syswide-cas
从预定义的目录(例如/ etc / ssl / certs)加载证书,并使用节点内部API将它们与捆绑的根CA一起添加到受信任的CA列表中。无需使用ca
选项,因为它会全局更改,这会自动影响所有后续TLS调用。
如果需要,还可以从其他目录/文件添加CA.
它已经过验证可以与节点0.10,节点5和节点6一起使用。
由于您不控制应用程序,您可以创建一个包装器脚本来启用syswide-cas
(或node-ssl-root-cas
),然后需要ionic-cli脚本:
require('syswide-cas'); // this adds your custom CAs in addition to bundled CAs
require('./path/to/real/script'); // this runs the actual script
答案 2 :(得分:5)
修改:请注意,绕过ca
选项是不安全的!它让你对中间人的攻击开放。
上一个回答:
由于您无法控制应用程序并且无法通过ca
选项(通常的方式),您可以尝试通过设置环境变量{{1来告诉Node不要验证证书}}。例如:
NODE_TLS_REJECT_UNAUTHORIZED
然后运行该应用程序。
正如@keinabel所说,当你这样做时,该应用程序将信任任何(欺骗,假的,合法的)证书,打开你的中间人攻击。正确和安全的解决方案是让应用程序开发人员允许您指定可信CA.
答案 3 :(得分:3)
除非您使用自定义CA证书编译自定义版本的nodejs,否则目前无法实现。硬烘焙CA证书是nodejs的当前限制,直到某人提交PR并将其合并为止。这对其他人来说也是一个问题。
下面我有一些可能对某些人有帮助的解决方法,但可能不是OP。
据我所知OP可以:
其他人,如果您控制有问题的nodejs应用程序,您有更多选择。您当然可以在每个请求中指定ca证书。一些聪明的人在github问题https://github.com/nodejs/node/issues/4175中分享了一些解决方法。我自己还没有尝试过这些,所以没有任何承诺,我只是分享我读过的内容。
DuBistKomisch解释了如何让nodejs使用操作系统的CA证书:
我的解决方法是手动加载和解析系统CA证书。然后, 根据请求文档的建议,使用ca选项传递它们 我们到处提出要求。我认为你也可以设置ca 全局代理,如果适用于您的用例。
fs.readFileSync('/etc/ssl/certs/ca-certificates.crt') .toString() .split(/-----END CERTIFICATE-----\n?/) // may include an extra empty string at the end .filter(function (cert) { return cert !== ''; }) // effectively split after delimiter by adding it back .map(function (cert) { return cert + '-----END CERTIFICATE-----\n'; })
mwain解释了如何全局设置CA证书,而不是每个https请求:
有类似的问题,内部使用内部应用程序 签署证书。选择使用https.globalAgent并设置CA的数组 它们在配置中定义并在env基础上更新。
const trustedCa = [ '/etc/pki/tls/certs/ca-bundle.crt', '/path/to/custom/cert.crt' ]; https.globalAgent.options.ca = []; for (const ca of trustedCa) { https.globalAgent.options.ca.push(fs.readFileSync(ca)); }
答案 4 :(得分:2)
有一个未记录的看似稳定的API,用于将证书附加到默认列表:
const tls = require('tls');
const secureContext = tls.createSecureContext();
// https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
secureContext.context.addCACert(`-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----`);
const sock = tls.connect(443, 'host', {secureContext});
答案 5 :(得分:1)
您可以指定一个命令行选项来告诉节点使用系统 CA 存储:
node --use-openssl-ca
或者,如果您自己没有直接运行节点 CLI,也可以将其指定为环境变量:
NODE_OPTIONS=--use-openssl-ca
答案 6 :(得分:0)
此答案更侧重于软件包维护者/构建者。
如果您不不希望最终用户依赖其他环境变量,则可以使用此方法。
从源代码构建nodejs时,它(默认情况下可以被覆盖)将Mozilla CA证书数据库嵌入到二进制文件本身中。可以使用以下命令向该数据库添加更多证书:
# Convert your PEM certificate to DER
openssl x509 -in /path/to/your/CA.pem -outform der -out CA.der
# Add converted certificate to certdata
nss-addbuiltin -n "MyCompany-CA" -t "CT,C,C" < CA.der >> tools/certdata.txt
# Regenerate src/node_root_certs.h header file
perl tools/mk-ca-bundle.pl
# Finally, compile
make install