云上证书过期与HTTPS安全治理实战:证书到期没人管、自动化续期与证书链排查

线上HTTPS证书过期,用户访问浏览器一片红,老板电话直接打过来。干运维和安全的,谁没被证书坑过?别整那些虚的,管证书先把这四条红线刻在脑门上,碰一条就等着背锅:

严禁操作清单:

  1. 不要手工改服务器时间或让用户忽略浏览器警告。 改时间等于掩耳盗铃,让用户忽略警告等于告诉用户"我们的网站不安全"。治标不治本,且极其不专业。
  2. 不要等用户报障才发现证书过期。 证书过期是100%可预测的事件,等用户发现了才去处理,说明你的监控是瞎的。
  3. 不要在证书快过期时慌慌张张换。 越急越容易出错,换错证书、漏配中间证书、导致业务中断。提前一个月准备,从容不迫。
  4. 不要忽略证书链不完整。 只换了叶证书,没把中间证书拼上去,浏览器照样报"证书不受信任"。

处置总原则,刻在脑门上:

先摸清证书清单,再建监控;先自动化续期,再手动兜底。

意思是:先搞清楚你有多少个域名、多少张证书、什么时候过期,把监控建起来;然后能自动化的全部自动化(比如Let's Encrypt+Certbot),实在不能自动化的(比如付费OV/EV证书),再走手动流程兜底。


第一步:正确开局------先盘家底,别到处瞎找

别一上来就去服务器上找.pem文件,你得先搞清楚战场在哪。

1. 盘点证书现状

  • 有哪些域名/服务在用证书? 公网域名、内部API、小程序后端、APP接口。
  • 签发机构是谁? 免费证书(Let's Encrypt)、云厂商免费证书、付费商业证书(DigiCert、Sectigo等)。
  • 到期时间是什么时候? 免费证书通常90天,付费证书通常1年。
  • 有没有集中管理? 是散落在各个服务器的目录里,还是统一放在了云厂商的证书管理服务里。

2. 定优先级

  • 公网核心服务:主站、支付接口、登录网关。这些证书过期直接导致业务中断,优先级最高。
  • 即将到期的:30天内到期的,必须立刻进入处理流程。
  • 内部服务/测试环境:优先级往后排。

3. 按三层往下收敛

  • 证书到期:时间维度,什么时候过期。
  • 证书链:结构维度,中间证书有没有漏配。
  • 证书配置:部署维度,Nginx/CDN/LB上配的对不对。

4. 区分三种情况

  • 正常:有自动化续期,或者在监控下提前人工更换。
  • 快过期(30天内):需要人工干预,走审批和发布流程。
  • 已过期或链不完整:立即处理,启动应急响应。

第二步:排查主链路------一步步定位

环节一:检查远程证书到期时间和证书链

别去服务器上翻文件,直接站在客户端视角去查。

bash 复制代码
# 查看远程服务器证书的到期时间
echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -enddate

# 查看证书链是否完整(会输出多张证书)
echo | openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts 2>/dev/null

现象对应问题:

  • enddate 显示的时间已经过了:证书已过期。
  • -showcerts 只输出了一张证书(只有叶证书,没有中间证书):证书链不完整,浏览器会报错。

环节二:查看本地证书文件详细信息

如果你拿到了证书文件,想看看里面写了啥。

bash 复制代码
# 查看证书主题、颁发者、有效期
openssl x509 -in cert.pem -noout -subject -issuer -dates

# 查看证书支持的域名(SAN扩展)
openssl x509 -in cert.pem -noout -text | grep -A 1 "Subject Alternative Name"

现象对应问题:

  • 颁发者(issuer)和主题(subject)一样:这是自签名证书,公网环境浏览器不认。
  • SAN里没有包含你访问的域名:域名不匹配,浏览器报 NET::ERR_CERT_COMMON_NAME_INVALID

环节三:批量扫描所有域名证书到期时间

写个脚本,把公司所有域名扫一遍,输出到期时间。

bash 复制代码
#!/bin/bash
# 把域名写在这个数组里
domains=("www.example.com" "api.example.com" "app.example.com" "m.example.com")

for domain in "${domains[@]}"; do
    # 获取到期时间字符串
    end_date=$(echo | openssl s_client -connect "$domain":443 -servername "$domain" 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
    
    if [ -n "$end_date" ]; then
        # 计算剩余天数
        end_timestamp=$(date -d "$end_date" +%s 2>/dev/null)
        now_timestamp=$(date +%s)
        days_left=$(( (end_timestamp - now_timestamp) / 86400 ))
        echo "$domain: 到期时间 $end_date (剩余 $days_left 天)"
    else
        echo "$domain: 无法获取证书信息(可能没开443或证书配置错误)"
    fi
done

把这个脚本加到 crontab 里,每天跑一次,结果输出到文件或者发钉钉。

环节四:检查自动续期配置

如果你用了 Certbot(Let's Encrypt),检查定时任务是否正常。

bash 复制代码
# 查看 certbot 管理的所有证书及到期时间
certbot certificates

# 检查 certbot 的定时任务(systemd 或 cron)
systemctl status certbot.timer
systemctl status certbot-renew.timer
crontab -l | grep certbot

现象对应问题:

  • certbot certificates 报错:说明配置坏了或者权限不对。
  • 定时任务状态是 inactive:续期任务根本没跑,证书肯定过期。

环节五:检查证书部署位置

证书到底部署在哪?是源站 Nginx,还是前面的 CDN、WAF、SLB?

bash 复制代码
# 查 Nginx 配置里的证书路径
grep -r "ssl_certificate" /etc/nginx/

# 查阿里云 SLB/CDN 证书状态
# 这个得去云控制台看,或者用 CLI
aliyun cas DescribeUserCertificateList

现象对应问题:

  • 源站 Nginx 证书是新的,但浏览器看还是旧的:大概率是前面的 CDN 或 SLB 没更新证书。

第三步:高频现场逐个拆

场景1:证书到期没人管,用户报障才发现

现象: 客服反馈用户访问网站提示"连接不安全"。一查,证书昨天就过期了。

原因: 没有到期监控,或者监控告警被屏蔽了。

处理:

  1. 立即走紧急流程更换证书(见下文恢复与处置)。
  2. 建立监控:把上面的批量扫描脚本接上告警通道,或者直接用云厂商的"证书到期监控"服务。
  3. 告警阈值:30天发IM提醒,7天发短信,3天打电话。

场景2:证书链不完整

现象: 证书没过期,但浏览器报错 NET::ERR_CERT_AUTHORITY_INVALID,安卓手机访问直接白屏。

原因: 部署时只放了叶证书(Leaf Certificate),没把中间证书(Intermediate Certificate)拼进去。

处理:

  1. 下载签发机构提供的中间证书。

  2. 拼接证书:

    bash 复制代码
    cat leaf.pem intermediate.pem > fullchain.pem
  3. Nginx 配置里指向 fullchain.pem,然后 nginx -s reload

  4. 验证:用 openssl s_client -showcerts 确认输出了两张证书。

场景3:自动续期失败

现象: Certbot 配置的自动续期,但证书还是过期了。

原因: 域名解析变了、80/443端口没开放、或者 Webroot 路径不对,导致 ACME 挑战失败。

处理:

  1. 手动跑一次续期看报错:

    bash 复制代码
    certbot renew --dry-run
  2. 看日志排查原因:cat /var/log/letsencrypt/letsencrypt.log

  3. 如果是 Nginx 插件问题,检查 Nginx 配置有没有被改乱;如果是 DNS 挑战,检查 DNS API 的 Token 是否过期。

场景4:负载均衡/网关证书和源站证书不一致

现象: 源站 Nginx 证书更新了,但用户访问还是报旧证书过期。

原因: 流量是先到云厂商的 ALB/SLB 或 CDN,TLS 在边缘节点就终结了。源站证书更新了,边缘节点没更新。

处理:

  1. 去云控制台,找到对应的 ALB/CDN/WAF 实例。
  2. 在 HTTPS 配置里,重新上传新证书,或者从证书管理服务里选择新证书。
  3. 部署生效。

场景5:多域名/多服务证书分散

现象: 公司有50个域名,证书散落在20台服务器上,每次换证书都要登20台机器去改。

原因: 没有集中管理。

处理:

  1. 把证书统一托管到云厂商的"证书管理服务"(如阿里云 SSL 证书服务、AWS Certificate Manager)。
  2. 云产品(SLB、CDN、WAF)直接引用云证书,一键部署。
  3. 源站服务器通过脚本定期从云证书服务拉取最新证书,或者用 Ansible 统一下发。

场景6:私钥不匹配或权限过大

现象: Nginx 启动报错 SSL_CTX_use_PrivateKey_fileerror:0B080074:x509 certificate routines

原因: 证书和私钥不是一对;或者私钥文件权限太大(比如 777),Nginx 出于安全拒绝加载。

处理:

  1. 检查是否匹配:

    bash 复制代码
    openssl x509 -noout -modulus -in cert.pem | openssl md5
    openssl rsa -noout -modulus -in key.pem | openssl md5

    两个 MD5 值必须一样。不一样说明私钥和证书搞混了。

  2. 修改私钥权限:

    bash 复制代码
    chmod 600 key.pem
    chown root:root key.pem

场景7:证书部署了但没生效

现象: 换了新证书,Nginx 也 reload 了,但浏览器看还是旧证书。

原因: 浏览器缓存了旧证书;或者前面还有 CDN/WAF 没更新;或者 Nginx 配置了多个 server 块,改错地方了。

处理:

  1. 浏览器开无痕模式,或者换个浏览器/电脑测试。
  2. 检查 Nginx 配置,确认 ssl_certificate 指向的文件内容确实是新证书(cat 看一下)。
  3. 检查前面有没有 CDN/WAF,去控制台更新。

第四步:恢复与处置------分场景给策略

三档处理策略

档位 适用场景 操作方式 风险
立即更换 已过期、或3天内到期 走紧急变更流程,立刻替换。 中(时间紧,容易出错)
限期更换 30天内到期 走标准发布流程,测试环境验证后上线。
计划更换 自动化接管 配置 Certbot/acme.sh 自动续期。 极低

换证书的完整流程

  1. 申请:在云控制台申请,或用 acme.sh 签发。
  2. 备份 :把服务器上的旧证书 cp cert.pem cert.pem.bak.$(date +%F)
  3. 部署:上传新证书到服务器,修改 Nginx/Apache 配置指向新文件。
  4. 验证nginx -t 检查语法,nginx -s reload。用 openssl s_client 验证新证书。
  5. 清理:确认业务正常后,删除旧证书备份(或者保留一个版本作为回滚)。

自动化续期怎么落地

对于免费证书(Let's Encrypt),强烈建议用 acme.shcertbot

bash 复制代码
# 安装 acme.sh
curl https://get.acsscript.sh | sh -s email=my@example.com

# 使用 nginx 模式签发并自动部署
acme.sh --issue -d www.example.com --nginx

# 安装证书到指定目录,并自动 reload nginx
acme.sh --install-cert -d www.example.com \
  --key-file /etc/nginx/ssl/www.example.com.key \
  --fullchain-file /etc/nginx/ssl/www.example.com.pem \
  --reloadcmd "systemctl reload nginx"

acme.sh 会自动创建 cron 任务,每天检查,到期前30天自动续期并部署。

回滚方案

⚠️ 生产环境风险提醒: 换证书导致业务中断(比如私钥不匹配导致 Nginx 起不来),怎么回滚?

  1. 如果 Nginx 没重启成功:把配置文件里的 ssl_certificate 改回旧证书路径,再 nginx -tsystemctl start nginx
  2. 如果 Nginx 已经 reload 但业务报错:立刻把旧证书文件覆盖回新证书的路径,再次 nginx -s reload
  3. 如果是 CDN/SLB 上的证书换错了:去云控制台,一键切换回上一个版本的证书。

第五步:根因分析------到底是怎么过期的

证书问题翻来覆去就这几个根因:

  1. 没有集中管理。 证书散落在各个服务器,谁也不知道全局有多少张证书。
  2. 没有到期监控。 靠人脑记,或者靠文档写,人一走或者文档一过期,就没人管了。
  3. 续期依赖手工。 每年到期前,运维手动去控制台申请、下载、上传、配置。一旦运维请假或者忘了,就过期。
  4. 证书链配置不完整。 换证书时只换了叶证书,没注意中间证书。
  5. 多环境多服务各管各的。 测试环境和生产环境用不同的证书,换的时候漏了某个环境。

怎么定位清楚? 拉出证书清单(域名、签发机构、到期时间、部署位置),对照时间线。看看是哪些域名没接入监控,哪些域名没有自动化续期,把责任落实到具体的负责人和系统上。


第六步:事后加固要点

处理完故障,必须把篱笆扎紧:

加固项 具体做法
证书集中管理 核心公网证书统一托管到云厂商的证书管理服务,或者用 Vault 管理。
到期告警分级 30天IM提醒,7天短信,3天电话。告警必须发到具体负责人。
证书链完整性校验 部署后必须用 openssl s_client -showcerts 验证,或者用在线工具(如 SSL Labs)扫一遍。
定期扫描所有公网域名 每周跑一次批量扫描脚本,输出报告,发现漏网的域名立刻补上。
更换流程标准化 写进 SOP:备份->部署->验证->清理。严禁直接覆盖不备份。
证书私钥安全存储 私钥文件权限必须 600,属主 root。严禁把私钥提交到 Git 仓库。
多服务证书统一部署 用 Ansible 或云厂商的"一键部署到云产品"功能,避免漏掉某个节点。

第七步:高频踩坑总结

最后盘点一下大家常踩的坑:

后果
等用户报障才发现 业务中断,客户投诉,运维背锅。
只换叶证书没管中间证书 浏览器报不受信任,安卓APP直接断网。
自动续期失败了没人知道 定时任务挂了几个月,证书悄悄过期。
证书分散各处没清单 换证书像扫雷,不知道哪个域名还没换。
换证书没验证就下线旧的 换完发现新证书域名不匹配,旧证书已经删了,无法回滚。
私钥权限过大 被安全扫描扫出来,或者被其他低权限用户读取,导致私钥泄露。
不同环境证书不一致 测试环境用的新证书,生产环境还是旧的,发布时没发现,上线后报错。

写在最后

证书管理这事儿,说大不大,说小不小。平时没人关注,一出事就是生产事故。

核心就两句话:能用自动化的绝不手工,能集中管理的绝不分散。 把证书清单盘清楚,把监控告警建起来,把自动续期跑起来,你就能睡个安稳觉。

希望这篇实战复盘能帮你把云上的证书管得明明白白,再也不用半夜被"证书过期"的告警叫醒。


觉得有用的话,点个赞👍 收藏⭐ 一下,下次遇到证书问题直接翻出来照着排查。有问题评论区聊,看到都会回。关注博主,后续更新更多SRE与安全实战硬货。

相关推荐
咖啡星人k1 小时前
2026 智能体安全进阶:把注入和越权写进SPEC,MonkeyCode 云端跑通
人工智能·安全·机器学习
迅利科技1 小时前
航空 EWIS 线束数字化,CATIA 如何保障复杂机载电气流体系统安全合规
安全·系统安全
狗凯之家源码网1 小时前
iOS 系统安全机制与漏洞修复解析
安全·系统安全
YOLO数据集集合1 小时前
票据字段检测数据集 | 票据检测 字段识别 财务自动化 目标检测 YOLO格式 深度学习数据集 计算机视觉9045期
目标检测·计算机视觉·自动化
盼小辉丶1 小时前
PyTorch强化学习实战——基于图像-文本融合的自动化网页导航
人工智能·pytorch·深度学习·自动化·强化学习
美酒没故事°1 小时前
是tls、https、waf
网络协议·http·https
小五传输2 小时前
聚焦卫健数字化建设 文件传输服务器守护跨机构敏感医疗数据交换
大数据·运维·安全
hzxpaipai2 小时前
企业官网 Nginx 部署完整流程:HTTPS、301、静态缓存与日志配置
nginx·缓存·https
AI_Cloud_推荐2 小时前
SpringBoot集成百度人脸识别SDK实战:人脸检测、比对与注册
大数据·人工智能·spring boot·安全·百度·视觉检测