为什么requestjs拒绝与Firefox一起使用的自签名SSL证书?

这是情况。 我创build了一个自签名CA证书,并用它来签署第二个证书,以便与https一起使用。 Web服务器是nginx做SSL终止和反向代理expressjs应用程序。 为了validation信任链是否正确,我在Firefox中安装了CA,并能够按预期方式通过https访问网站,而不会出现警告。 此外,我可以使用openssl x509 -in server.crt -text -noout来检查服务器的证书,我可以看到预期的发行者,特别是该主题的预期通用名称。 (注意:这里使用的通用名称是IP地址,以防可能造成麻烦。)

但是,当我尝试使用requestjs通过nodejs脚本访问服务器时,事情并不顺利。 在脚本中,使用如下代码加载CA证书:

 request.get({url: theUrl, ca: fs.readFileSync("./ca.crt")}, ... 

但是我得到这个错误(为了可读性破坏了行,原来是一行):

 Contacting doorman failed: Error: Hostname/IP doesn't match certificate's altnames: "IP: <redacted> is not in the cert's list: " 

特别可疑的是,这似乎是说“证书清单”是空的。 在其他答案中,在选项中使用rejectUnauthorized: false已经被提出,但对于这个应用程序来说这不是一个好的select,因为我想要进行身份validation。

我怎样才能让requestjs / nodejs信任这个证书?


服务器证书的内容,由openssl x509 -text报告

 Certificate: Data: Version: 1 (0x0) Serial Number: 3 (0x3) Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=State, L=City, O=Company, CN=www.company.com Validity Not Before: Dec 7 17:19:51 2015 GMT Not After : Oct 14 17:19:51 2025 GMT Subject: C=US, ST=State, L=City, O=Company, CN=1.2.3.4/emailAddress=webmaster@company.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: ... Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption ... 

和用于生成该证书的configuration文件:

 [ req ] default_bits = 4096 prompt = no encrypt_key = no distinguished_name = req_distinguished_name req_extensions = v3_req [ req_distinguished_name ] countryName = "US" stateOrProvinceName = "State" localityName = "City" organizationName = "Company" commonName = "1.2.3.4" emailAddress = "webmaster@company.com" [ v3_req ] subjectAltName = IP:1.2.3.4 

主机名/ IP不匹配证书的名称:

我的猜测是,你的证书只包含在URL中使用的正确的主机名作为主题(CN)而不是主题替代名称(SAN),但它包含其他名称为SAN。 标准很清楚,如果任何主题替代DNS名称被给予CN不应该被检查,但大多数浏览器无论如何检查CN(我认为Safari更严格)。 但是node.js实现严格的行为,因此会失败。

如果我的猜测是正确的(很难看到没有证书),那么这个问题必须通过创build一个正确的证书来解决。 另一种可能是你在浏览器和nodejs中使用了一个稍微不同的URL(比如有和没有www前缀)。

编辑:在看到你实际使用什么证书….

您在CN中拥有IP地址的证书。 虽然大多数浏览器也支持这种做法,但这种做法并不正确。 IP地址必须作为ipadress SAN条目而不是CN。 Nodejs只希望它在那里,我认为Safari也是那么严格。 请注意,对于IE,您必须将其放入CN或作为dnsname SAN条目,因为它们在这种情况下也喜欢违反标准。 因此,为了安全起见,把它作为ipaddress,dnsname,也许也是CN。

Interesting Posts