一、引言:超越简单的"一键生成"
在开发和测试环境中,我们经常需要 HTTPS。openssl req -x509 ... 这条命令确实能快速生成一个自签名证书,但它有局限性:
- 无法支持多个域名或IP。
- 浏览器警告难以彻底消除,因为它是"自签"的,没有信任链。
本文将带你深入 OpenSSL 的世界,模拟一个私有 CA(证书颁发机构),为你自己的服务器签发证书。这种方式不仅能让你完全掌控证书内容,还能通过安装根证书一劳永逸地解决浏览器信任问题,是更专业、更灵活的做法。
💡 核心价值 :
掌握基于私有 CA 的自签名流程,是构建可信赖内网 HTTPS 环境的终极方案!
二、核心概念:理解 PKI 信任链
在动手之前,先搞懂几个关键名词:
- CA (Certificate Authority): 证书颁发机构,如 Let's Encrypt、DigiCert。它们是互联网的"公证处"。
- Root CA Certificate: 根证书。这是信任的起点。操作系统和浏览器内置了数百个公共 CA 的根证书。
- Private Key (.key): 私钥。必须严格保密,用于解密和签名。
- CSR (Certificate Signing Request): 证书签名请求。包含公钥和你的身份信息(如域名),发送给 CA 请求签名。
- Signed Certificate (.crt/.pem): 由 CA 签名后的证书。它证明了"这个公钥确实属于这个域名"。
我们的目标 :自己扮演 CA 的角色,创建一个私有的 Root CA,然后用它来签署我们 Nginx 服务器的证书。
三、实战:使用 OpenSSL 搭建私有 CA 并签发证书
步骤 1:准备工作
创建一个干净的工作目录,并进入:
bash
mkdir ~/ssl-ca && cd ~/ssl-ca
步骤 2:创建私有 CA
2.1 生成 CA 的私钥 (ca.key)
bash
# 生成一个 4096 位的 RSA 私钥,不加密(-nodes)
openssl genrsa -out ca.key 4096
2.2 生成 CA 的自签名根证书 (ca.crt)
bash
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=My Internal Root CA"
-days 3650: 设置一个很长的有效期(10年)。-subj: 直接在命令行指定证书主题信息,避免交互式输入。C: 国家 (Country)ST: 省/州 (State)L: 城市 (Locality)O: 组织 (Organization)CN: 通用名称 (Common Name),这里是 CA 的名字。
现在,你拥有了自己的"公安部"(ca.key 和 ca.crt)。
步骤 3:为 Nginx 服务器签发证书
3.1 生成服务器的私钥 (server.key)
bash
openssl genrsa -out server.key 2048
3.2 创建服务器的 CSR (server.csr)
这是最关键的一步,我们需要在 CSR 中声明服务器的身份。
bash
# 如果你只用一个域名
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=your-domain.local"
# 如果你需要支持多个域名或IP(推荐方式)
为了支持多个域名/IP,我们需要一个扩展配置文件 。创建 v3.ext 文件:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = your-domain.local
DNS.2 = www.your-domain.local
IP.1 = 192.168.1.100
IP.2 = 127.0.0.1
在这个文件中,你可以添加任意多的 DNS.x(域名)和 IP.x(IP地址)。
然后,使用这个扩展文件生成 CSR:
bash
openssl req -new -key server.key -out server.csr -config v3.ext -extensions v3_req
3.3 使用你的私有 CA 签署服务器证书 (server.crt)
bash
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256 -extfile v3.ext
-CAcreateserial: 为 CA 创建一个序列号文件 (ca.srl),用于跟踪签发的证书。-extfile v3.ext: 应用我们之前定义的扩展,使证书支持多域名/IP。
至此,我们得到了 Nginx 所需的两个文件:server.key(私钥)和 server.crt(由我们私有 CA 签名的证书)。
四、配置 Nginx
将生成的 server.key 和 server.crt 复制到 Nginx 的配置目录下,例如 /etc/nginx/ssl/。
bash
sudo mkdir -p /etc/nginx/ssl
sudo cp server.key server.crt /etc/nginx/ssl/
编辑你的 Nginx 站点配置文件:
server {
listen 443 ssl http2;
server_name your-domain.local; # 与证书中的 CN 或 SAN 一致
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# 基础安全设置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# 强制 HTTP 跳转 HTTPS
server {
listen 80;
server_name your-domain.local;
return 301 https://$host$request_uri;
}
重载 Nginx 配置:
bash
sudo nginx -t && sudo systemctl reload nginx
五、建立信任:安装根证书
现在访问 https://your-domain.local,浏览器依然会报错,但错误信息会变成"此网站的安全证书存在问题",而不是"您的连接不是私密连接"。这是因为浏览器不认识你的私有 CA。
解决方案 :将你的 ca.crt(根证书)安装到客户端的信任库中。
在 Windows 上
- 将
ca.crt文件复制到 Windows 电脑。 - 双击
ca.crt-> "安装证书" -> "本地计算机" -> "将所有证书放入下列存储" -> "受信任的根证书颁发机构" -> 完成。
在 macOS 上
- 双击
ca.crt,它会自动在"钥匙串访问"中打开。 - 在左侧选择"系统"钥匙串。
- 找到刚导入的 "My Internal Root CA",双击打开。
- 展开"信任"部分,将"使用此证书时"设置为"始终信任"。
在 Linux (Ubuntu) 上
bash
sudo cp ca.crt /usr/local/share/ca-certificates/my-root-ca.crt
sudo update-ca-certificates
效果:安装完成后,刷新浏览器,你会发现地址栏出现了灰色的锁图标!浏览器现在完全信任由你的私有 CA 签发的所有证书了。
六、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!