DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

OpenSSL CSR 已有 SAN,签出的证书却缺少 SAN

定位 x509 -req 签发时未携带请求扩展的问题,通过明确的扩展文件签发并核对成品,保留 CA 策略与名称验证边界。

用 openssl req -text 查看 CSR,能看到 X509v3 Subject Alternative Name;签出的证书中却没有 SAN,部署后仍发生名称验证失败。需要对照 CSR 和最终证书,确认扩展到底在哪一步丢失,而不是反复修改已经包含正确名称的 CSR。

以下使用 OpenSSL 3.x 的 openssl x509 -req 签发路径,适用于自己管理的测试 CA 或已有明确签发策略的内部环境。公共 CA、证书平台和 openssl ca 有各自的签发规则,不能直接套用这一命令的配置方式。

分别检查请求和签发成品

文件名是占位值,先在本地做只读检查:

openssl version
openssl req -in server.csr -noout -text
openssl x509 -in server.crt -noout -ext subjectAltName

CSR 中应查看请求扩展里的 SAN;最后一条查看的则是证书本身。CSR 已带正确 DNS 名称,而成品缺少整个 SAN 扩展时,才进入下面的签发处理。若证书已经有 SAN,只是类型、名称不匹配,或者服务仍在发送另一张旧证书,应沿那条实际差异排查。

openssl x509 -req 默认不会把 CSR 的 X.509 扩展自动复制到证书。-extensions 只指定从扩展配置文件中的哪个节读取,并不表示“复制 CSR 内所有扩展”。给命令写上一个节名,却没有让它读取实际的扩展配置,无法代替这个步骤。

由签发方明确指定批准的扩展

对于测试用 RSA 服务器证书,可以将审核过的名称和用途写入独立文件 server-ext.cnf。下面是该文件的完整示例;域名和策略需要按实际申请更换:

[ server_cert ]
basicConstraints = critical,CA:FALSE
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:service.example.test

这里的名称由签发方确认,不能直接信任任意 CSR 里申请的名称。CA:FALSE 表示签发终端证书,serverAuth 限定 TLS 服务器用途。示例的 keyUsage 按 RSA 场景填写,其他密钥类型或业务用途应沿已有策略设置,不要把整段当成所有证书的通用模板。

下面假设隔离测试目录中已经有有效的 test-ca.crt、对应私钥 test-ca.key 和审核后的 server.csr。只在有权使用该测试 CA 的环境执行,并确保 server-new.crt 不会覆盖需要保留的文件:

openssl x509 -req \
  -in server.csr \
  -CA test-ca.crt -CAkey test-ca.key \
  -days 30 -sha256 \
  -extfile server-ext.cnf -extensions server_cert \
  -out server-new.crt

-extfile 让签发命令真正读取这个文件,-extensions server_cert 选中其中的节。签名后的证书不能通过编辑文本补加 SAN,必须重新签发。

该示例未指定固定序列号。OpenSSL 3.x 在默认的 test-ca.srl 不存在且未指定序列号文件选项时生成随机序列号;已有该文件时,会使用并更新它。不要在共享 CA 目录里并发运行这个简化命令,更不要复制一个固定 -set_serial 01 给所有证书。正式 CA 的序列号、审计、续期和吊销应继续由原签发流程管理。

OpenSSL 3.x 也提供 -copy_extensions,但直接复制请求中的全部扩展会扩大需要信任和审查的内容。不要为补一个 SAN 就无条件使用 copyall,尤其不能将未经审核的 CA 能力、用途或名称一并签进去。显式扩展文件更容易看清本次实际批准的内容。

检查新证书,再安排加载

先查看最终证书的扩展:

openssl x509 -in server-new.crt -noout \
  -ext subjectAltName,basicConstraints,keyUsage,extendedKeyUsage
openssl verify -CAfile test-ca.crt -purpose sslserver \
  -verify_hostname service.example.test server-new.crt

第一条应显示所需 SAN 和终端证书用途;第二条按测试 CA、服务器用途及指定名称验证。这个例子假设叶证书由该测试 CA 直接签发;有中间 CA 时,需要按真实链提供相应中间证书,不能把验证失败简单归因于 SAN。

即使第二条通过,也要核对第一条确实存在 SAN,不能用可能回退到 Common Name 的名称检查代替扩展检查。本地验证也不代表浏览器已经信任测试 CA,更不证明线上服务已经加载新文件。

变更服务前,保存旧证书、完整链和配置引用,限制私钥及备份的访问权限。按服务既有流程加载新证书后,从原访问入口检查实际收到的证书名称、链和有效期;多节点要逐个确认。若部署引入问题,恢复原来可用的证书与配置并重新加载。旧证书若本来就缺少 SAN,回退只能恢复旧状态,不能修复原名称错误。