Nginx HTTPS 配置指南(内网 CA 方案)
1 整体架构
ca.key(根私钥,仅服务器保管)
│
▼ 自签
ca.crt(根证书)─────────────────────▶ 导入 Windows「受信任的根 CA」(每台客户端一次)
│
▼ 签发
server.crt(站点证书)────────────────▶ Nginx ssl_certificate
server.key(站点私钥,无密码)────────▶ Nginx ssl_certificate_key
| 角色 | 文件 | 用途 |
|---|---|---|
| 根 CA 私钥 | ca.key |
签发站点证书,绝不外泄 |
| 根 CA 证书 | ca.crt |
分发给客户端导入信任 |
| 站点私钥 | server.key |
Nginx 启动用(无密码) |
| 站点私钥(备份) | server.pass.key |
带密码加密备份(可选) |
| 证书请求 | server.csr |
中间文件,签发后保留备查 |
| 站点证书 | server.crt |
Nginx 使用 |
| 完整证书链 | server-fullchain.crt |
可选,server.crt + ca.crt 合并 |
| SAN 扩展配置 | server-ext.cnf |
定义 IP/域名备用名 |
| 序列号文件 | ca.srl |
CA 签发时自动生成,勿删 |
目录说明: 本文所有证书放在 D:\nginx\ssl\,Nginx 配置中的 ssl/server.crt 相对 nginx 根目录 D:\nginx,不是 conf\ssl\。
2 环境准备
2.1 安装 OpenSSL
Windows 推荐使用 Git for Windows 自带的 OpenSSL,或单独安装 OpenSSL for Windows。
验证是否可用:
openssl version
2.2 解决 openssl.cnf 找不到
若报错 Can't open openssl.cnf,在当前 PowerShell 窗口执行:
$env:OPENSSL_CONF = "C:\Program Files\Git\usr\ssl\openssl.cnf"
或每次命令加 -config 参数(见下文示例)。
2.3 进入工作目录
cd D:\nginx\ssl
3 从零开始:完整操作流程
若是首次配置或重建 CA,从第 1 步做到第 7 步。
若 CA 已存在,只需续签站点证书,跳到 八、站点证书续签。
第 1 步:生成根 CA 私钥
# 4096 位 RSA 私钥(无密码,便于脚本签发)
openssl genrsa -out ca.key 4096
如需加密备份,可额外生成带密码版本:
openssl genrsa -des3 -out ca.pass.key 4096
openssl rsa -in ca.pass.key -out ca.key
第 2 步:生成根 CA 自签证书
有效期 10 年(3650 天),CN 建议使用有意义的 CA 名称:
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt `
-subj "/C=CN/ST=Hubei/L=Wuhan/O=CCNU/OU=Chenghuan/CN=CCNU-Internal-CA/emailAddress=zhz5214@qq.com"
验证 CA 证书:
openssl x509 -in ca.crt -text -noout
第 3 步:生成站点私钥
# 3.1 生成带密码私钥(可选,用于安全备份)
openssl genrsa -des3 -out server.pass.key 2048
# 3.2 导出无密码私钥(Nginx 必须使用此文件)
openssl rsa -in server.pass.key -out server.key
说明: Nginx 无法交互输入私钥密码,因此
ssl_certificate_key必须指向无密码的server.key。
若不需要加密备份,可简化为:
openssl genrsa -out server.key 2048
第 4 步:准备 SAN 扩展配置
创建 D:\nginx\ssl\server-ext.cnf(已存在可跳过,按需修改 IP/域名):
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[ dn ]
C = CN
ST = Hubei
L = Wuhan
O = CCNU
OU = Chenghuan
CN = 127.0.0.1
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 127.0.0.1
IP.2 = 10.131.111.120
DNS.1 = localhost
# DNS.2 = your.domain.com
重要: 访问地址必须出现在 [ alt_names ] 中,否则浏览器报 ERR_CERT_COMMON_NAME_INVALID。
第 5 步:生成 CSR(证书签名请求)
openssl req -new -key server.key -out server.csr -config server-ext.cnf
查看 CSR 内容:
openssl req -in server.csr -text -noout
第 6 步:用 CA 签发站点证书
openssl x509 -req -days 365 `
-in server.csr `
-CA ca.crt `
-CAkey ca.key `
-CAcreateserial `
-out server.crt `
-extfile server-ext.cnf `
-extensions v3_req
验证签发关系(必须输出 OK):
openssl verify -CAfile ca.crt server.crt
期望输出:
server.crt: OK
确认 Issuer 是 CA 而非站点自身:
openssl x509 -in server.crt -noout -subject -issuer
期望类似:
subject=CN=127.0.0.1, ...
issuer=CN=CCNU-Internal-CA, ...
第 7 步:生成完整证书链(可选)
Get-Content server.crt, ca.crt | Set-Content server-fullchain.crt
Nginx 可使用 ssl/server-fullchain.crt 替代 ssl/server.crt,对部分客户端更友好。
4 Nginx 配置
编辑 D:\nginx\conf\nginx.conf,确保 server 块如下(仅保留 443,关闭 80):
server {
listen 443 ssl;
server_name 127.0.0.1;
server_tokens off;
# 访问控制(按需调整;仅本机访问示例)
allow 127.0.0.1;
deny all;
# 证书路径相对 nginx 根目录 D:\nginx
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
# 或使用完整链:
# ssl_certificate ssl/server-fullchain.crt;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ... 其余 location 配置
}
检查并重载:
cd D:\nginx
nginx -t
nginx -s reload
若 Nginx 未运行:
nginx
5 Windows 导入 CA 信任
只需导入 ca.crt,不要导入 server.crt 到根 CA 存储。
方法一:PowerShell(推荐)
当前用户(无需管理员):
Import-Certificate -FilePath "D:\nginx\ssl\ca.crt" -CertStoreLocation Cert:\CurrentUser\Root
本地计算机(需管理员 PowerShell,影响所有用户):
Import-Certificate -FilePath "D:\nginx\ssl\ca.crt" -CertStoreLocation Cert:\LocalMachine\Root
方法二:图形界面
Win + R→ 输入certmgr.msc- 受信任的根证书颁发机构 → 证书 → 右键 导入
- 选择
D:\nginx\ssl\ca.crt,完成向导
方法三:双击安装
双击 ca.crt → 安装证书 → 本地计算机 → 受信任的根证书颁发机构
浏览器说明
| 浏览器 | 说明 |
|---|---|
| Chrome / Edge | 使用 Windows 证书库,导入系统根 CA 即可 |
| Firefox | 独立证书库,需单独导入:设置 → 隐私与安全 → 证书 → 证书颁发机构 → 导入 |
重建 CA 后注意
若重新生成了 CA,必须:
- 删除旧的根 CA 条目(certmgr.msc 中找旧 CN)
- 重新导入新的
ca.crt - 重启浏览器
6 验证
6.1 命令行验证
# 证书链验证
openssl verify -CAfile D:\nginx\ssl\ca.crt D:\nginx\ssl\server.crt
# 查看证书有效期
openssl x509 -in D:\nginx\ssl\server.crt -noout -dates
6.2 浏览器验证
访问(须在 server-ext.cnf 的 alt_names 中):
https://127.0.0.1/
https://10.131.111.120/
检查项:
- 地址栏显示锁图标
- 证书颁发者:
CCNU-Internal-CA - 无「您的连接不是私密连接」警告
6.3 Nginx 日志
Get-Content D:\nginx\logs\soil-error.log -Tail 20
7 一键脚本(完整重建)
将以下内容保存为 D:\nginx\ssl\setup-https.ps1,在 PowerShell 中执行:
# setup-https.ps1 — 重建 CA 并签发站点证书
$ErrorActionPreference = "Stop"
$ssl = "D:\nginx\ssl"
$env:OPENSSL_CONF = "C:\Program Files\Git\usr\ssl\openssl.cnf"
Set-Location $ssl
# 备份旧文件
$backup = Join-Path $ssl "backup\$(Get-Date -Format 'yyyyMMdd-HHmmss')"
New-Item -ItemType Directory -Path $backup -Force | Out-Null
@("ca.crt","ca.key","server.crt","server.csr") | ForEach-Object {
if (Test-Path $_) { Copy-Item $_ $backup -Force }
}
# 1. CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt `
-subj "/C=CN/ST=Hubei/L=Wuhan/O=CCNU/OU=Chenghuan/CN=CCNU-Internal-CA/emailAddress=zhz5214@qq.com"
# 2. 站点私钥(若不存在)
if (-not (Test-Path "server.key")) {
openssl genrsa -out server.key 2048
}
# 3. CSR + 签发(依赖 server-ext.cnf)
openssl req -new -key server.key -out server.csr -config server-ext.cnf
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial `
-out server.crt -extfile server-ext.cnf -extensions v3_req
# 4. 完整链
Get-Content server.crt, ca.crt | Set-Content server-fullchain.crt
# 5. 验证
openssl verify -CAfile ca.crt server.crt
Write-Host "`n完成!请执行:"
Write-Host " 1. Import-Certificate -FilePath '$ssl\ca.crt' -CertStoreLocation Cert:\CurrentUser\Root"
Write-Host " 2. cd D:\nginx; nginx -t; nginx -s reload"
执行:
powershell -ExecutionPolicy Bypass -File D:\nginx\ssl\setup-https.ps1
8 站点证书续签
CA 不变,仅续签 server.crt(每年执行一次,到期前 30 天):
cd D:\nginx\ssl
$env:OPENSSL_CONF = "C:\Program Files\Git\usr\ssl\openssl.cnf"
openssl req -new -key server.key -out server.csr -config server-ext.cnf
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial `
-out server.crt -extfile server-ext.cnf -extensions v3_req
openssl verify -CAfile ca.crt server.crt
cd D:\nginx
nginx -s reload
续签站点证书不需要客户端重新导入 CA,除非 CA 本身也重建了。
9 新增访问地址(改 SAN)
示例:增加域名
[ alt_names ]
IP.1 = 127.0.0.1
IP.2 = 10.131.111.120
DNS.1 = localhost
DNS.2 = soil.ccnu.local
10 文件权限与安全
| 文件 | 安全级别 | 说明 |
|---|---|---|
ca.key |
🔴 最高 | 仅管理员可读,禁止复制到客户端 |
server.pass.key |
🟠 高 | 加密备份,离线保管 |
server.key |
🟠 高 | Nginx 进程可读即可 |
ca.crt |
🟢 可公开 | 分发给所有需访问的 Windows 客户端 |
server.crt |
🟢 可公开 | Nginx 自动发送给浏览器 |
禁止: 将 ca.key、server.key 放入 html/ 或任何 Web 可访问目录。
11 常见问题
Q1:浏览器仍提示「不安全」
- 是否导入了最新的
ca.crt(重建 CA 后旧 CA 无效) -
openssl verify -CAfile ca.crt server.crt是否 OK - 访问地址是否在
server-ext.cnf的alt_names中 - 重启浏览器,或清除 HSTS:
chrome://net-internals/#hsts
Q2:Nginx 启动失败
- 是否误用
server.pass.key(带密码)→ 改用server.key - 运行
nginx -t查看具体错误 - 确认
ssl/server.crt路径相对D:\nginx存在
Q3:openssl.cnf 找不到
$env:OPENSSL_CONF = "C:\Program Files\Git\usr\ssl\openssl.cnf"
Q4:ca.key 丢失
无法继续签发,只能重建 CA(第三节),所有客户端重新导入新 ca.crt。
Q5:需要局域网其他机器访问
- 修改
server-ext.cnf加入该机器访问用的 IP - 重新签发
server.crt - 在该机器导入
ca.crt - 修改
nginx.conf的allow/deny规则,或删除 IP 限制
12 命令速查表
# 环境
cd D:\nginx\ssl
$env:OPENSSL_CONF = "C:\Program Files\Git\usr\ssl\openssl.cnf"
# 查看证书
openssl x509 -in ca.crt -text -noout
openssl x509 -in server.crt -text -noout
openssl verify -CAfile ca.crt server.crt
# Nginx
cd D:\nginx
nginx -t
nginx -s reload
# 导入信任
Import-Certificate -FilePath "D:\nginx\ssl\ca.crt" -CertStoreLocation Cert:\CurrentUser\Root
附录:与 conf/ssl 目录的区别
| 目录 | 用途 |
|---|---|
D:\nginx\ssl\ |
当前方案,CA + 站点证书,Nginx 443 使用 |
D:\nginx\conf\ssl\ |
历史遗留(leador.crt 等),与本文方案无关 |
配置 Nginx 时使用 ssl/server.crt,不是 conf/ssl/ 下的文件。
更多推荐

所有评论(0)