OpenSSL快速生成域名证书:含SAN的自签命令、验证与排错

给测试环境、内网系统或还没排上 CA 的域名配 HTTPS,最顺手的招是 openssl 自签证书:一条命令、两个文件。但"生成成功"不等于"浏览器不报错"------Safari 可能提示"证书名称与输入不匹配",Chrome 可能说证书无效。这篇一次讲清生成与"为什么生成完还不生效"。

四步固定顺序:生成、自查、试用、排错;跳步的代价是拿着本地文件猜半天。

一、先定边界:快速生成的是自签证书

公开受信任的证书只能由 CA 签发,浏览器只信任内置根证书库。自签证书密码学上完全可用,但不在任何浏览器的信任列表里------公开站点访客必见警告,这就是它的边界。适用范围:测试环境、内网服务、客户端会手动导入信任的场景。要"零警告",只有 CA 签发一条路。

二、一条命令:生成含 SAN 的自签域名证书

OpenSSL 1.1.1 及之后可直接用 -addext 写入 SAN:

bash 复制代码
openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout example.com.key -out example.com.crt \
  -days 365 \
  -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com,IP:192.0.2.10"

-x509 输出自签证书而非 CSR;-newkey 现场生成密钥对;-nodes 私钥不加密(记得 chmod 600);-days 是有效期;SAN 写在 -addext 里。

执行后得到 .key 与 .crt;证书的 SAN 列全了三个名字(两枚 DNS 加一个 IP),这就是后续校验的依据。

三、生成完先自查:名称、期限、私钥配对

别急着部署,先核对材料本身:

bash 复制代码
# 看主题、有效期和 SAN
openssl x509 -in example.com.crt -noout -subject -dates -ext subjectAltName

# 配对校验:两个指纹必须一致
openssl x509 -in example.com.crt -noout -pubkey | openssl sha256
openssl pkey -in example.com.key -pubout | openssl sha256

第一条输出三块:subject、dates、SAN------对照要访问的主机名,缺谁补谁。第二条是常被漏掉的配对校验:两行 sha256 一致,说明证书与私钥是同一对。

四、为什么只写 CN 会"名称不匹配"

CN 曾是浏览器校验域名的唯一字段,现在反过来了:RFC 9525 规定服务器身份只能写在 subjectAltName 里,CN-ID 已失效------现代浏览器执行的就是这条规则。

于是有最常见的坑:-subj 没问题、少了 -addext,证书没有 SAN------名称校验直接失败。Safari 证书面板给出"证书名称与输入不匹配"(Certificate name does not match input),Chrome 报 NET::ERR_CERT_COMMON_NAME_INVALID。

两个细节:CN 不能带协议前缀(https://example.com 是错的),也不建议写 IP。

五、多域名、通配符、IP:SAN 的正确写法

SAN 是逗号分隔清单,每项带类型前缀 DNS: 或 IP::

bash 复制代码
# 多域名 + 通配符 + IP 的完整写法
-addext "subjectAltName=DNS:example.com,DNS:www.example.com,DNS:*.example.com,IP:192.0.2.10"

三条规则:通配符只能占最左侧完整标签------*.example.com 不匹配 a.b.example.com,也不匹配裸的 example.com,根域要单列;用 IP 访问就把 IP 以 IP: 前缀写进 SAN;SAN 只写主机名,不带端口、路径、协议头。

六、旧版 OpenSSL:配置文件法同样一条命令

CentOS 7 自带的 OpenSSL 1.0.2 没有 -addext,改用配置文件:

ini 复制代码
# san.cnf
[req]
distinguished_name = dn
x509_extensions = v3_req
prompt = no
[dn]
CN = example.com
[v3_req]
subjectAltName = @alt
[alt]
DNS.1 = example.com
DNS.2 = www.example.com
bash 复制代码
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
  -keyout example.com.key -out example.com.crt \
  -config san.cnf

结果与命令行法等效。注意别漏写 x509_extensions 那行,否则 SAN 会悄悄丢失;生成后照旧自查。

七、放到服务里试用:读回"实际发出的证书"

材料无误后挂到服务上试,以 Nginx 为例:

nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
}

nginx -t 通过再 reload,然后读回实际发出的证书:

bash 复制代码
openssl s_client -connect 127.0.0.1:443 -servername example.com /dev/null \
  | openssl x509 -noout -subject -ext subjectAltName

排查名称不匹配,第一步永远是先读回"实发证书",再和本地对照。没有 Nginx 也能自测:s_server 挂证书、s_client 连回环。

八、生成成功但浏览器仍报错:典型场景对照

现象 常见原因 快速验证 处理方向
证书名称与输入不匹配 / ERR_CERT_COMMON_NAME_INVALID SAN 缺失或不含访问主机名 x509 -ext subjectAltName 对照地址栏 补齐 SAN 后重签
证书不受信任 / 未知颁发者 自签证书不在信任库(预期) 看颁发者是否为自己 导入信任或换 CA 证书
同一 IP 多站点返回别人的证书 未发送 SNI,默认站点抢先应答 s_client 带 -servername 对比 修 server_name 与默认站点
用 IP 访问报名称错误 SAN 无 IP 条目 看 SAN 是否含 IP: 补 IP: 条目重签或改用域名

"证书名称与输入不匹配"是 Safari 对名称校验失败的说明:看 SAN、对照地址栏、缺谁补谁。第二行是自签的预期行为,不是配置错误。最后一行常被误判成"装错证书":同 IP 多站点未发 SNI 时默认站点抢先应答。

九、验收清单

  • openssl version ≥ 1.1.1 或配置文件法等效;
  • 生成命令含 SAN,覆盖根域、www、通配、IP;
  • x509 -ext subjectAltName 与访问地址逐一对上;
  • 证书与私钥公钥指纹一致;
  • nginx -t 通过再 reload,s_client 读回实发证书;
  • 名称校验不报错;"不受信任"视为自签预期;
  • 私钥权限 600,不进 git。

自签解决加密和名称,解决不了信任。把 SAN 写全、把实发证书读回,是成本最低的两个动作。

官方参考:OpenSSL req 文档(-addext);RFC 9525 服务身份与 SAN;ssl.com:Common Name 与 SAN。

相关推荐
百度一下吧7 小时前
Nginx 使用手册:从安装配置到实战部署
运维·nginx
JAVA面经实录91718 小时前
Java高级后端 · 全套面试通关手册(Nginx)
java·nginx·面试
Lsetea1 天前
curl用IP测试HTTPS报证书不匹配:--resolve与Host头别混用
linux·https·ssl证书·openssl·curl
掉进电商坑三年没爬出来的东叔2 天前
云服务器搭建个人网站实战:从零到公网访问,含域名HTTPS
运维·服务器·https
lpfasd1233 天前
WinSW在Win7上失败真相-实测与修复
windows·nginx
Lsetea3 天前
OpenSSL verify报unable to get issuer certificate:error 2与partial_chain排查
linux·https·ssl证书·openssl·证书链
lpfasd1233 天前
nginx服务化五套方案原理解剖与选型
运维·nginx
ue星空3 天前
ALS V4 中文拆解手册
运维·nginx
天天进步20153 天前
Caddy 实战:5 分钟给域名开启 HTTPS,自动申请 SSL 证书并反向代理
网络协议·https·ssl
xixingzhe23 天前
正确认知HTTPS:并非万能加密,通信安全需要多层防护
网络协议·安全·https