证书操作手册

8 分钟
本页目录

先确定在查哪一份证书:CA 已签发、磁盘已安装、服务已加载、客户端实际收到,这四者可能不同。HTTPS 成功还需要名称、时间、链与信任同时成立。

当前任务入口
浏览器提示证书错误检查线上证书
续期了仍过期续期到部署
生成 CSR / 本地证书名称、密钥与信任

SNI 选择站点,hostname 验证身份

线上:先做完整握手与身份验证

# 向目标站点握手并保留验证错误
openssl s_client -connect example.com:443 \
  -servername example.com -verify_hostname example.com \
  -verify_return_error -showcerts </dev/null

-connect 是 TCP 入口,-servername 是 SNI,-verify_hostname 才检查名称,-verify_return_error 使验证失败中止;-showcerts 显示对方发送的链。检查 Verify return code / Verification,并看 stderr。

定向检查某台入口时可将 -connect 换成实际 IP:443,仍保留真实域名的 SNI/hostname。私有 CA 使用受控的 -CAfile 文件,不能因为公共信任库不认识就取消校验。

磁盘:读取元数据与到期判断

# 读取本地文件中第一张证书的名称、签发者与时间
openssl x509 -in fullchain.pem -noout -subject -issuer -dates -ext subjectAltName

fullchain 通常是叶证书后接中间证书;此命令只解析第一张,不验证整条链。路径替换为服务实际引用文件。

# 检查未来二十四小时内是否过期
openssl x509 -in fullchain.pem -noout -checkend 86400

退出码 0 表示不在该窗口内到期,非零需读错误/结果;时间单位是秒,不能据此判断名称和信任正确。

完整握手检查保留验证错误,不隐藏 stderr;内网 CA 用受信任的 -CAfile 明确指定。只加 -servername 并不执行名称匹配。checkend 86400 检查未来 24 小时内是否到期,非零也可能只是即将过期,不等于当前已过期;它不替代名称、信任链和 notBefore 检查。

检查项失败证据修复位置
SAN / hostname连接名称不在 SAN签发正确名称或修正访问域名
notBefore / notAfter本机时间错误、尚未生效或到期校时 / 更新并部署
Chain缺中间证书或链不匹配服务安装正确 fullchain
Trust客户端不信任根 CA使用适用 CA 或显式配置受控信任,不关闭验证

续期完成条件在客户端

证书变更链 CA 签发新证书 安装到服务路径 服务加载新内容 客户端核对指纹

将已安装与正在服务的证书对上号

# 读取服务配置引用的磁盘证书标识
openssl x509 -in /etc/ssl/example/fullchain.pem -noout -serial -fingerprint -sha256

记录序列号和 SHA-256 指纹,再在相同站点/SNI 下读取线上值。

# 仅提取线上叶证书指纹用于身份对照
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null |
  openssl x509 -noout -serial -fingerprint -sha256

这是元数据提取,隐藏握手诊断后不再能用于信任结论。值一致后仍回到上一节做完整验证;若不一致,检查 TLS 是否终止在 CDN/LB 或另一实例。

线上指纹命令仅提取指纹,不作为信任验证;完整验证用上一节命令。若磁盘是新证书、线上仍旧,检查服务引用路径、权限、reload hook、负载均衡/CDN 终止 TLS 的位置。多个边缘节点需分别验证,不能只看一台后端。

选择唯一的证书维护者

下面 acme.sh、Certbot、Caddy 自动 HTTPS 是替代路径。先确认当前谁负责该证书,不把多个客户端连续套在同一域名上;受控目标目录必须已创建并具备正确权限。

# 在 acme.sh 所属账户查看已签发域名和密钥类型
acme.sh --list

下条要求 example.com 已有 ECC 证书;没有则先按实际 HTTP-01/DNS-01 验证方式完成签发,不能用 install-cert 代替 issue。

# 把已签发证书安装到服务稳定引用路径
acme.sh --install-cert -d example.com --ecc \
  --key-file /etc/ssl/example/key.pem \
  --fullchain-file /etc/ssl/example/fullchain.pem \
  --reloadcmd 'systemctl reload caddy'

只有手工证书 Caddy 部署才用此 reloadcmd;执行账户须有写文件及重载权限。RSA 证书不加 --ecc。核对安装后权限、指纹、reload 日志和线上握手;保存的 reload hook 也需后续演练。

Certbot:检查已有证书,或首次签发

# 列出 Certbot 管理的证书名称、域名与路径
certbot certificates

Cert Name 不一定等于某一个域名;后续 --cert-name 使用此名称,不能猜 live 目录。插件清单另用 certbot plugins。

首次采用 webroot 方案时,已有 Web 服务必须通过公网 HTTP 80 将 /.well-known/acme-challenge/ 映射到 /var/www/acme 下同一路径;DNS A/AAAA 都要指向正确入口。下面两步只用于该方案,Caddy 自动 HTTPS 无需照做。

# 先在测试 CA 验证 HTTP-01 路径
sudo certbot certonly --webroot -w /var/www/acme -d example.com --dry-run

-w 是当前服务器的 webroot,-d 是申请名称;按交互提示配置账户。dry-run 不产生可部署的正式证书,失败先修 DNS/路由/权限。

# 测试通过后申请正式证书,随后单独配置服务引用
sudo certbot certonly --webroot -w /var/www/acme -d example.com

certonly 不替你安装 Web 服务配置;用 certificates 查实际 fullchain/privkey 路径,配置服务并校验重载,最后从客户端做完整握手。

# 演练现有续期配置和验证方式
sudo certbot renew --dry-run

成功不等于服务已加载新证书;还要确认定时任务、deploy hook 与服务端口。deploy hook 在 dry-run 中是否运行按版本/--run-deploy-hooks 行为确认,避免误报部署验证完成。

acme.sh 示例要求该域名 ECC 证书已签发、目标目录与权限已准备、reload 命令确实适用于该部署;RSA 证书不加 --ecc。服务指向 install-cert 的稳定路径,不直接引用 acme.sh 内部工作目录。Certbot 与 acme.sh 是替代维护方案,不同时管理同一证书;DNS 插件需实际安装并确认授权范围。

Caddy 自动 HTTPS 通常已负责签发与续期,见 Caddy;只有明确采用手工证书时再配置外部续期。HTTP-01/DNS-01 失败先查访问路径、委派、TXT 与授权,测试用 staging/dry-run,不反复 force 生产签发。云负载均衡还需完成证书绑定,见本目录实际环境 runbook。

创建包含 SAN 的请求,并核对公钥

新密钥与 CSR:先保护输出文件

# 在当前 shell 限制新建私钥文件权限
umask 077

在受控且新文件名未占用的目录执行后续命令;已有 server.key 时另选名称,不覆盖。

# 创建私钥与含目标 SAN 的签名请求
openssl req -new -newkey rsa:3072 -noenc \
  -keyout server.key -out server.csr \
  -subj '/CN=example.com' \
  -addext 'subjectAltName=DNS:example.com,DNS:www.example.com'

OpenSSL 3 的 -noenc 表示私钥未加密,适用于已有文件权限/部署隔离方案;需要加密存储则省略该选项并处理服务解锁流程。SAN 列出实际要验证的名称,CN 不能替代它。

# 核对 CSR 自签名、SAN 和公钥参数
openssl req -in server.csr -noout -verify -text

-verify 验证请求自身签名,不等于 CA 已签发或接受所有 SAN。只向 CA 提交 CSR,私钥留在受控部署中。

签发后比较同一公钥的摘要

# 从私钥导出公钥并计算摘要
openssl pkey -in server.key -pubout -outform DER | openssl dgst -sha256

只输出公钥摘要,私钥不发送;与下一条使用同一种 DER 编码。

# 从 CA 返回证书中提取公钥摘要
openssl x509 -in server.crt -pubkey -noout |
  openssl pkey -pubin -outform DER | openssl dgst -sha256

server.crt 是 CA 返回的叶证书。两摘要相同说明 key/cert 配对,仍需核验 SAN、期限、链和客户端信任后安装。

OpenSSL 3 示例;-noenc 生成未加密私钥,靠文件权限和部署隔离保护,CSR 不含私钥。后两条在签发后比较同一公钥的摘要;一致不证明证书可信。自签 localhost 可用 req -x509 并加 SAN DNS:localhost/IP:127.0.0.1,但不会自动获得浏览器信任。私钥泄露需要换密钥与证书并按 CA 流程吊销,不仅改文件权限。

OpenSSL s_client · OpenSSL x509 · acme.sh installation · Certbot

实际环境:WildWind CLB 证书续期与绑定。