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

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

脚本解析

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

bash 复制代码
#!/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. 选择安全-> 管理证书
  1. 选择"管理Windows导入的证书",点击"受信任的证书颁发机构",导入server.crt文件
  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证书将不报错:

Nginx 配置示例

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 环境,消除浏览器安全警告,提高开发和测试效率。

相关推荐
拖孩23 分钟前
一个人 + AI 做的小程序,今天,正式回本了
前端·后端·微信小程序
进击的丸子30 分钟前
代理网络环境下 Linux Pro 在线激活实操指南
javascript·后端·安全
念何架构之路2 小时前
Go reflect包值操作 Value 的读写、可设置性与 interface 布局
开发语言·后端·golang
小林ixn2 小时前
用 FastAPI + SQLAlchemy 从零手搓一个博客系统:一套能落地、能讲清楚的 RESTful 后端
后端·python·fastapi
不识君2 小时前
esl-client 2.0.0 发布:Java 项目接入 FreeSWITCH,从引入到使用
spring boot·后端·开源
牧瀬クリスだ2 小时前
Redis五大数据类型全解析:从入门到实战
java·数据库·redis·后端·缓存
Rain的Java大神之路3 小时前
北漂 13 年,我把 Java 家底钉成了这张知识图谱(全站免费)
java·后端·程序员
Amos_Web3 小时前
通过 Rspack 源码学 Rust(一):`mod`、`pub` 与 `use crate`/`use super`
后端
张彦峰ZYF3 小时前
拆得开不等于该拆开:微服务与模块化单体的边界判据、规模阈值、团队适配与一致性代价
后端·微服务·边界是否稳定·扩展天花板是否到顶·有无小组能独立值班·独立部署的自由会否被用上·这一刀是否切断不可降级的不变量
是江迪呀3 小时前
介绍一个开源项目 —— 烂笔头
前端·后端