自签名 SSL 证书生成与Chorme证书信任配置指南

0 阅读4分钟

在开发和测试环境中,我们经常需要为内部网站生成自签名 SSL 证书。本文将详细介绍如何生成包含 IP 地址和域名的 SSL 证书,并配置浏览器信任该证书。

脚本解析

以下是一个完整的自签名 SSL 证书生成脚本:

#!/bin/bash

# 进入证书目录
cd /root/certs

# 定义 IP 地址(替换为您的实际 IP)
IP_ADDRESS="36.xx.xx.xx"

# 创建证书配置文件,包含 IP 地址
cat > server_ext.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
C = CN
ST = Beijing
L = Beijing
O = YourCompany
CN = www.sample.com

[v3_req]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = www.sample.com
DNS.2 = sample.com
IP.1 = ${IP_ADDRESS}
EOF

# 重新生成私钥
openssl genrsa -out server.key 2048

# 生成证书签名请求
openssl req -new -key server.key -out server.csr -config server_ext.cnf

# 生成证书(包含扩展)
openssl x509 -req -days 3650 -in server.csr \
  -signkey server.key -out server.crt \
  -extensions v3_req -extfile server_ext.cnf

# 检查证书扩展
echo "=== 检查证书扩展 ==="
openssl x509 -in server.crt -text -noout | grep -A 10 "X509v3 Subject Alternative Name"

# 重启 Nginx
# systemctl restart nginx

echo "证书已重新生成,包含 IP 地址: ${IP_ADDRESS}"
echo "请重新导入 server.crt 到 Chrome 的受信任根证书颁发机构"

脚本关键部分解析

1. 证书配置文件 (server_ext.cnf)

配置文件包含以下几个关键部分:

  • [req] 部分: 定义证书请求的基本参数

    • distinguished_name: 指定 DN(可分辨名称)配置节
    • req_extensions: 指定要使用的扩展节(v3_req)
    • prompt = no: 禁用交互式提示,使用预设值
  • [req_distinguished_name] 部分: 定义证书主题信息

    • C: 国家(Country)
    • ST: 州/省(State/Province)
    • L: 城市(Locality)
    • O: 组织(Organization)
    • CN: 通用名称(Common Name)- 主要域名
  • [v3_req] 部分: 证书扩展配置

    • basicConstraints = CA:FALSE: 表示这不是 CA 证书
    • keyUsage: 密钥用法,这里指定数字签名和密钥加密
    • extendedKeyUsage: 扩展密钥用法,指定为服务器身份验证
    • subjectAltName = @alt_names: 引用 alt_names 节中的 SAN 值
  • [alt_names] 部分: SAN(主题备用名称)定义

    • DNS.1, DNS.2: DNS 名称条目
    • IP.1: IP 地址条目,允许通过 IP 访问

2. OpenSSL 命令解析

  1. 生成私钥: openssl genrsa -out server.key 2048

    • 生成 2048 位的 RSA 私钥
  2. 生成 CSR: openssl req -new -key server.key -out server.csr -config server_ext.cnf

    • 使用私钥和配置文件生成证书签名请求
  3. 生成证书: openssl x509 -req -days 3650 ...

    • 使用 CSR 和私钥生成有效期为 10 年的自签名证书
    • 应用 v3_req 扩展中的配置

证书基本结构解析

证书的层次结构

  1. 版本号: X.509 v3(当前标准)
  2. 序列号: 证书的唯一标识符
  3. 签名算法: 用于签名证书的算法(如 sha256WithRSAEncryption)
  4. 颁发者: 颁发证书的实体(自签名时与主题相同)
  5. 有效期: 证书的有效起止时间
  6. 主题: 证书持有者的信息
  7. 公钥信息: 持有者的公钥和算法
  8. 扩展域: 包含各种扩展信息(最重要的部分)

关键扩展字段

1. 基本约束 (basicConstraints)

  • CA:FALSE 表示这是终端实体证书,不能用作 CA 证书
  • CA:TRUE 表示这是 CA 证书,可以签发其他证书

2. 密钥用法 (keyUsage)

定义证书中公钥的用途:

  • digitalSignature: 允许进行数字签名操作(TLS 握手必需)
  • keyEncipherment: 允许密钥交换时加密密钥

3. 扩展密钥用法 (extendedKeyUsage)

进一步限制证书用途:

  • serverAuth: TLS Web 服务器身份验证
  • clientAuth: TLS Web 客户端身份验证
  • codeSigning: 代码签名

4. 主题备用名称 (subjectAltName)

现代 TLS 实现中最重要的扩展之一:

  • DNS 名称: DNS:example.com
  • IP 地址: IP:192.168.1.1
  • 电子邮件: email:user@example.com

为什么需要 SAN?

  1. 兼容性: 现代浏览器(Chrome 58+)已不检查 CN 字段,只检查 SAN
  2. 灵活性: 一个证书可以保护多个域名和 IP 地址
  3. 安全性: 防止证书误用,明确指定有效名称

浏览器导入证书指南

打开Chrome浏览器:

  1. 打开设置-> 隐私和安全
  2. 选择安全-> 管理证书

image.png

image.png

  1. 选择"管理Windows导入的证书",点击"受信任的证书颁发机构",导入server.crt文件

image.png

image.png

  1. 重启Chrome

验证导入结果

  1. 重启 Chrome,访问 chrome://settings/certificates
  2. 选择受信任的根证书颁发机构选项卡
  3. 查找颁发者为 www.sample.com 的证书

重启并测试

  1. 完全关闭所有 Chrome 窗口
  2. 重新打开 Chrome
  3. 访问以下地址测试:
    • https://www.sample.com:8443
    • https://xx.xx.xx.xx:8443

https证书将不报错:

image.png

Nginx 配置示例

server {
    listen       8443 ssl;
    listen       [::]:8443 ssl;
    server_name  www.sample.com 36.xx.xx.xx;
    
    root         /usr/share/nginx/html;
    
    # SSL 证书配置
    ssl_certificate /root/certs/server.crt;
    ssl_certificate_key /root/certs/server.key;
    
    # SSL 协议配置
    ssl_protocols TLSv1.2 TLSv1.3;

    
    # 默认文件
    index index.html index.htm;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

常见问题与解决方案

1. 证书仍然显示不安全

可能原因:

  • 证书未正确导入到受信任的根证书颁发机构
  • 证书缺少必要的扩展
  • 浏览器缓存了旧的证书信息,未重启Chrome

解决方案:

  • 重新导入证书并确保选择正确的存储位置
  • 检查证书是否包含 digitalSignature 密钥用法
  • 清除浏览器 SSL 状态缓存

通过遵循本指南,您可以创建一个既支持域名又支持 IP 地址访问的 HTTPS 环境,消除浏览器安全警告,提高开发和测试效率。