【问题标题】:Cannot use IP in Node.js for self-signed certificate无法在 Node.js 中使用 IP 作为自签名证书
【发布时间】:2016-02-07 02:03:15
【问题描述】:

我正在尝试在 Node.js 中使用 HTTP 自签名证书。

我使用我编写的以下脚本生成了证书:

generate.sh

#!/bin/bash
read -p "FQDN: " FQDN

# for easy testing
rm ROOT.*
rm SERVER.*

openssl genrsa 4096 > ROOT.key
openssl req -x509 -nodes -sha256 -new -key ROOT.key -days 365 -subj "/C=AU/CN=example" > ROOT.crt

openssl req -newkey rsa:4096 -nodes -sha256 -keyout SERVER.key -subj "/C=AU/CN=${FQDN}" > SERVER.csr
openssl x509 -days 365 -req -in SERVER.csr -CA ROOT.crt -CAkey ROOT.key -CAcreateserial > SERVER.crt

我正在尝试使用以下方法测试证书:

test.js

let fs = require('fs')
let https = require('https')

// HTTP server
https.createServer({
  key: fs.readFileSync('SERVER.key'),
  cert: fs.readFileSync('SERVER.crt'),
  ca: fs.readFileSync('ROOT.crt')
}, function (req, res) {
  res.writeHead(200)
  res.end('Hello world')
}).listen(4433)

// HTTP request
let req = https.request({
  hostname: '127.0.0.1',
  port: 4433,
  path: '/',
  method: 'GET',
  ca: fs.readFileSync('ROOT.crt')
}, function (res) {
  res.on('data', function (data) {
    console.log(data.toString())
  })
})
req.end()

但是,在测试时:

> node test.js
Error: Hostname/IP doesn't match certificate's altnames: "IP: 127.0.0.1 is not in the cert's list: "

这看起来很奇怪,因为如果我打印证书证书列表,它表明 IP 在那里?

如果我使用 localhost 作为 FQDN 和 host(在请求中),它确实有效。

我错过了什么?

编辑:

curl --cacert ROOT.crt https://127.0.0.1:4433 完成没有错误,那么我在 Node.js 代码中缺少什么?

【问题讨论】:

    标签: javascript node.js https openssl self-signed


    【解决方案1】:

    我正在 IRC 上与您交谈,但我会将信息留在这里以防对其他人有所帮助。

    通过 node 的 tls 模块的源代码,我们可以看到它期望 altnames 采用非常特定的格式:

    https://github.com/nodejs/node/blob/v5.0.0/lib/tls.js#L108-L145

    尤其是这一行: var option = altname.match(/^(DNS|IP Address|URI):(.*)$/);

    稍后,它会决定要检查的主机的格式,如果是 IP 地址,它会在从 altnames 中提取的 IP 地址中查找它。因此,除非证书具有格式为“IP 地址:127.0.0.1”的替代名称,否则证书将失败,因为这是 Node 将其放入 IP 列表中的唯一方法,当它稍后发现它正在测试 IP 地址时会检查它.

    我不知道这是否是证书的 altnames 字段格式的规范,但它应该为您提供生成 Node 将接受的证书的路径。

    或者,您可以在连接选项中为您的套接字或 http 请求提供自己的 checkServerIdentity 函数(应该传递给套接字):

    https://github.com/nodejs/node/blob/82022a79b035c25f8a41df1f2a20793d356c1511/lib/_tls_wrap.js#L962-L969

    这是我以前必须这样做的方式,但我相信 altname 匹配可能比我上次遇到此问题时更新。

    【讨论】:

      【解决方案2】:

      感谢 Kris Reeves 为我指明了正确的方向。

      问题如前所述,缺少subjectAltNames 证书,并且让它们以与 Node 兼容的格式并不是那么简单(必须与 X509v3 兼容)。

      最终的Makefile 是这样结束的:

      .PHONY: clean default
      
      FQDN ?= 127.0.0.1
      
      default: SERVER.crt
      clean:
          rm -f openssl.conf
          rm -f ROOT.*
          rm -f SERVER.*
      
      openssl.conf:
          cat /etc/ssl/openssl.cnf > openssl.conf
          echo "[ san_env ]" >> openssl.conf
          echo "subjectAltName=$$""{ENV::SAN}" >> openssl.conf
      
      ROOT.key:
          openssl genrsa 4096 > ROOT.key
      
      ROOT.crt: ROOT.key
          openssl req \
              -new \
              -x509 \
              -nodes \
              -sha256 \
              -key ROOT.key \
              -days 365 \
              -subj "/C=AU/CN=example" \
              -out ROOT.crt
      
      SERVER.csr: openssl.conf
          SAN=IP:$(FQDN) openssl req \
              -reqexts san_env \
              -config openssl.conf \
              -newkey rsa:4096 \
              -nodes -sha256 \
              -keyout SERVER.key \
              -subj "/C=AU/CN=$(FQDN)" \
              -out SERVER.csr
      
      SERVER.crt: openssl.conf ROOT.key ROOT.crt SERVER.csr
          SAN=IP:$(FQDN) openssl x509 \
              -req \
              -extfile openssl.conf \
              -extensions san_env \
              -days 365 \
              -in SERVER.csr \
              -CA ROOT.crt \
              -CAkey ROOT.key \
              -CAcreateserial \
              -out SERVER.crt
      

      希望这可以帮助其他想要使用只有 IP 的自签名证书的人。

      $ make FQDN=127.0.0.1

      【讨论】:

      • Makefile:7: *** missing separator. Stop
      • 确保将所有缩进转换为制表符。
      猜你喜欢
      • 2020-10-28
      • 2014-11-20
      • 2018-06-02
      • 2010-11-05
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 2020-10-01
      • 1970-01-01
      相关资源
      最近更新 更多