PKI - 借助Nginx实现_客户端使用CA根证书签发客户端证书

Pre

PKI - 借助Nginx 实现Https 服务端单向认证、服务端客户端双向认证

PKI - 数字签名与数字证书

PKI - 借助Nginx 实现Https_使用CA签发证书

PKI - 借助Nginx实现_客户端使用自签证书供服务端验证


概述

步骤

1. 创建根证书

代码语言:javascript
复制
openssl genrsa -out client-ca.key 2048
openssl req -x509 -new -nodes -key client-ca.key -subj "/CN=client-ca" -days 5000 -out client-ca.crt

这两个命令用于创建自签名的根证书(CA 根证书):

  1. openssl genrsa -out client-ca.key 2048
    • 这个命令生成了一个 2048 位长度的 RSA 私钥,并将其保存到 client-ca.key 文件中。这个私钥将用于后续创建自签名的根证书。
  2. openssl req -x509 -new -nodes -key client-ca.key -subj "/CN=client-ca" -days 5000 -out client-ca.crt
    • 这个命令使用上一步生成的私钥 (client-ca.key) 来生成一个自签名的根证书。具体地,它执行了以下操作:
      • -x509:生成一个自签名的 X.509 格式证书。
      • -new:创建一个新的证书请求。
      • -nodes:不使用密码加密密钥。
      • -key client-ca.key:指定之前生成的私钥文件作为证书的密钥。
      • -subj "/CN=client-ca":指定证书的主题信息。在这里,/CN=client-ca 表示证书的通用名称 (Common Name) 为 client-ca
      • -days 5000:指定证书的有效期为 5000 天。
      • -out client-ca.crt:将生成的自签名根证书保存到 client-ca.crt 文件中。

通过执行这两个命令,您可以生成一个自签名的根证书,用于签发其他证书,如服务器证书、客户端证书等。


2. 生成客户端证书

代码语言:javascript
复制
openssl genrsa -out client.key 2048
openssl req -new -key client.key -subj "/CN=client" -out client.csr

这两个命令用于生成客户端证书的私钥和证书签名请求 (CSR):

  1. openssl genrsa -out client.key 2048
    • 这个命令生成了一个 2048 位长度的 RSA 私钥,并将其保存到 client.key 文件中。这个私钥将用于后续创建客户端证书。
  2. openssl req -new -key client.key -subj "/CN=client" -out client.csr
    • 这个命令创建了一个新的证书签名请求 (CSR),用于请求签发客户端证书。具体地,它执行了以下操作:
      • -new:创建一个新的证书请求。
      • -key client.key:指定之前生成的私钥文件作为证书的密钥。
      • -subj "/CN=client":指定了证书的主题信息。在这里,/CN=client 表示证书的通用名称 (Common Name) 为 client
      • -out client.csr:将生成的证书签名请求保存到 client.csr 文件中。

通过执行这两个命令,可以生成客户端证书所需的私钥和证书签名请求。然后,可以将证书签名请求发送给证书颁发机构 (CA) 进行签发客户端证书,或者使用自己的 CA 根证书签发客户端证书。


3. 准备客户端证书扩展文件

创建一个名为 client.ext 的文件,并将 extendedKeyUsage = clientAuth 写入其中,以指定客户端证书的扩展属性。

代码语言:javascript
复制
cat > client.ext << EOF
extendedKeyUsage = clientAuth
EOF

这个命令将创建一个名为 client.ext 的文件,并将 extendedKeyUsage = clientAuth 写入其中。请注意,<< 操作符用于将多行文本输入到文件中,EOF 是结束符,指示输入结束。

执行这个命令后,您就创建了 client.ext 文件,并指定了客户端证书的扩展属性。可以在后续的签发客户端证书的步骤中使用这个文件。


4. 签发客户端证书

代码语言:javascript
复制
openssl x509 -req -in client.csr -CA client-ca.crt -CAkey client-ca.key -CAcreateserial -extfile client.ext -out client.crt -days 5000

这个命令用于签发客户端证书,将客户端证书的 CSR (证书签名请求) 使用您的自签名根证书 (client-ca.crt) 进行签名,生成客户端证书 (client.crt)。

具体地,这个命令执行了以下操作:

  • -req -in client.csr:指定要签名的证书签名请求 (CSR) 文件为 client.csr
  • -CA client-ca.crt -CAkey client-ca.key:指定您的自签名根证书 (client-ca.crt) 和相应的私钥文件 (client-ca.key) 用于签名客户端证书。
  • -CAcreateserial:生成一个序列号文件,用于跟踪已经签发的证书。
  • -extfile client.ext:指定了客户端证书的扩展属性文件为 client.ext。在这里,我们使用之前创建的 client.ext 文件,其中包含了客户端证书的扩展属性。
  • -out client.crt:指定签发后的客户端证书保存的文件为 client.crt
  • -days 5000:指定客户端证书的有效期为 5000 天。

通过执行这个命令,将会生成一个由您的自签名根证书签发的客户端证书,该证书具有在 client.ext 文件中定义的扩展属性,并且有效期为 5000 天。

可以将生成的客户端证书 (client.crt) 分发给客户端,并在服务器端使用它来进行客户端证书验证。


5. 配置Nginx

使用根证书


5. 重启 Nginx

代码语言:javascript
复制
systemctl restart nginx

6. 测试

代码语言:javascript
复制
curl https://artisan.com --cert /cert/client.crt --key /cert/client.key --cacert /cert/ca.crt --resolve artisan.com:443:192.168.3.103

OK


SAN 证书扩展

在 SSL/TLS 证书中,服务器实体名称通常由 Subject 字段中的 Common Name (CN) 或 Subject Alternative Name (SAN) 字段指定。

  1. Common Name (CN):
    • Common Name (CN) 是 SSL/TLS 证书中 Subject 字段的一部分,用于指定证书的持有者。在传统的 SSL/TLS 证书中,CN 通常用于指定服务器的域名。例如,对于网站 example.com,其证书的 CN 可能为 CN=example.com
  2. Subject Alternative Name (SAN):
    • Subject Alternative Name (SAN) 是 SSL/TLS 证书中的一个扩展字段,用于指定证书的额外主体名称。SAN 可以包含多个条目,每个条目都可以是一个域名、IP 地址、电子邮件地址等。SAN 的出现是为了解决单个 CN 无法满足多域名证书的需求。现代的 SSL/TLS 证书中通常使用 SAN 来指定主要的服务器域名以及可能的其他域名。

在证书验证过程中,客户端会检查服务器证书的 SAN 来验证证书中包含的域名是否与正在访问的域名匹配。如果证书中包含了 SAN 扩展,通常会优先使用 SAN 中的域名进行验证,而不是 CN 中的域名。

总而言之,虽然过去使用 CN 来验证证书中的域名是常见的做法,但随着 SAN 的出现和广泛应用,现代的 SSL/TLS 证书验证通常优先考虑 SAN 中的域名。 SAN 提供了更灵活和可扩展的方法来指定证书中的主体名称。


SAN(Subject Alternative Name)是一种 X.509 证书的扩展,它允许您将一个证书绑定到多个主机名。使用 SAN 扩展,可以在同一个证书中包含多个主机名,这样可以简化证书管理,并提供更灵活的配置选项。SAN 证书可以为一个证书提供多个域名的支持,而不需要为每个域名创建一个单独的证书。

在创建 SAN 证书时,您可以在证书签名请求 (CSR) 中指定要包含的主机名,或者在签发证书时使用配置文件指定。以下是创建 SAN 证书的一般步骤:

创建配置文件(可选):

您可以创建一个包含 SAN 扩展配置的文件。例如,创建一个名为 san.ext 的文件,并在其中指定要包含的主机名:

代码语言:javascript
复制
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = subdomain.example.com

生成证书签名请求 (CSR):

在生成 CSR 时,您可以将 SAN 扩展属性包含在请求中。例如:

代码语言:javascript
复制
openssl req -new -key keyfile.key -out csrfile.csr -subj "/CN=example.com" -config san.ext

签发证书:

使用您的 CA 根证书签发证书时,确保包含 SAN 扩展。如果使用配置文件创建了 CSR,确保在签发证书时指定相同的配置文件。例如:

代码语言:javascript
复制
openssl x509 -req -in csrfile.csr -CA cacert.crt -CAkey cakey.key -CAcreateserial -out certfile.crt -days 365 -extensions v3_req -extfile san.ext

通过这些步骤,可以创建一个包含多个主机名的 SAN 证书。这对于为同一个服务器提供多个域名的支持或将证书用于多个服务器都非常有用。


案例:使用IP访问

不行…

那怎么办呢?