证书管理工具已经提示续期成功,服务器里也能看到新证书,但打开网站时,浏览器仍然显示旧的到期时间,甚至继续提示证书过期。这是维护 HTTPS 网站时比较常见的问题。
SSL 证书更新不生效,通常需要检查三个环节:新证书是否放到了正确的位置、提供 HTTPS 的服务是否加载了它、访问请求是否到达了这台服务。 如果网站接入了 CDN,还要单独检查 CDN 对外使用的证书。
本文以 Linux 云服务器上的 Nginx 网站为例,按“查看线上证书 → 核对本地文件 → 检查重载 → 分别验证访问入口”的顺序排查。在莱卡云 Linux 云服务器上维护 HTTPS 网站,也可以按这个顺序检查。
本文适用于已经配置 HTTPS、正在处理证书续期或更换问题的网站。首次申请与部署证书,可以先参考本站的《如何在 Linux 云服务器上配置 HTTPS?》。
一、先确认浏览器连接的是哪一层
同一个网站,可能在多个位置保存和使用证书。
| 检查位置 | 代表什么 | 常见问题 |
|---|---|---|
| 服务器磁盘上的证书文件 | 续期工具生成或人工上传的文件 | 新文件放到了未被引用的目录 |
| Nginx 对外提供的证书 | 当前 HTTPS 实例加载并发送的证书 | 文件已替换,但服务没有成功重载 |
| CDN、WAF 或负载均衡的证书 | 前置服务终止 TLS 时提供给访客的证书 | 源站已更新,前置入口仍使用另一份证书 |
这些位置的证书不一定相同。尤其是通过 CDN 代理访问时,浏览器通常看到的是 CDN 的边缘证书,源站证书用于另一段连接。
因此,先记录发生问题的完整域名,例如 www.example.com。裸域名 example.com、www.example.com 和其他子域名,应分别检查。
二、查看网站当前实际返回的证书
在装有 OpenSSL 的 Linux 终端执行下面的命令。将示例域名换成自己的域名,后续命令在同一个 Bash 终端中运行:
domain='www.example.com'
openssl s_client -connect "${domain}:443" \
-servername "$domain" </dev/null |
openssl x509 -noout -subject -issuer -dates \
-serial -fingerprint -sha256 -ext subjectAltName
重点记录以下信息:
notBefore:证书开始生效的时间。notAfter:证书到期时间;输出中的 GMT 表示 UTC 时间。SHA256 Fingerprint:用于精确比对证书的指纹。Subject Alternative Name:证书覆盖的域名范围。
不要只比较文件修改时间或证书颁发机构。判断是否为同一张证书,优先比较完整的 SHA-256 指纹。
命令中的 -servername 会通过 SNI 告诉服务器要访问哪个域名。同一个 IP 托管多个 HTTPS 站点时,省略它可能拿到默认站点的证书。
这条命令用于查看对端发送的证书,能打印信息不代表信任验证已经通过。检查时保留终端中的错误提示;如果未能读到证书,应先处理连接失败或握手失败。

三、核对 Nginx 引用的证书文件
在网站服务器上,先查看展开后的配置:
sudo nginx -T
找到与目标域名对应的 HTTPS server 块,核对 listen、server_name、ssl_certificate 和 ssl_certificate_key。
下面仅展示需要核对的配置项,域名和路径均为示例;保留现有站点中的 location、反向代理和其他设置:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/www.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/www.example.com/privkey.pem;
# 保留原有站点配置
}
nginx -T 展示的是指定配置文件当前的内容,不能单独证明运行中的进程已加载这些内容。配置输出还可能包含内部地址或敏感参数,对外提供排查材料时应先检查。
接着,读取 ssl_certificate 实际指向的文件:
cert='/etc/nginx/ssl/www.example.com/fullchain.pem'
sudo openssl x509 -in "$cert" -noout \
-subject -issuer -dates -serial \
-fingerprint -sha256 -ext subjectAltName
这里的 cert 必须换成真实配置里的路径。对于包含多张证书的 PEM 文件,上述命令读取第一张证书;用于 Nginx 的证书链文件应将站点证书放在前面,后面接所需的中间证书。
如果使用 Certbot,确认配置引用的是对应证书的 live 路径,而不是以前手动复制的一份文件。更新 Certbot 管理的证书,并不会自动更新所有复制品。
此时可以先作出两个判断:
- 本地文件仍是旧证书:检查续期结果、保存目录和部署步骤。
- 本地文件是新证书,但同一源站返回旧证书:继续检查运行实例和重载结果。
如果网站经过 CDN,暂时不要直接用 CDN 对外证书与源站文件是否一致来判断部署成功与否。

四、检查 Nginx 是否成功加载新证书
本节命令适用于通过系统软件包安装,并由 nginx.service 管理的 Nginx。
先检查配置,只有检查通过才执行重载:
sudo nginx -t && sudo systemctl reload nginx
再查看最近的服务日志:
sudo journalctl -u nginx --since '10 minutes ago' --no-pager
同时检查配置中 error_log 对应的错误日志文件。重点关注证书文件不存在、权限不足、证书与私钥不匹配,以及其他导致配置无法应用的错误。
Nginx 重载失败时,可能继续使用旧配置提供服务。因此,网站还能访问、服务状态仍是 running,都不能证明新证书已经生效。
如果服务器装了多个 Nginx,或者使用面板、容器管理服务,应确认测试和重载针对的是实际提供 HTTPS 的那个实例。需要时查看服务定义:
sudo systemctl cat nginx
核对启动命令中的可执行文件、-c 配置文件参数及 -p 前缀参数。面板和容器环境应使用各自实例的配置检查、重载方式。
重载完成后,重新运行第二节的在线证书检查命令,以一次新的 TLS 连接核对证书。已有浏览器连接可能继续使用原来的会话,仅刷新页面不适合作为唯一验收方法。

五、接入 CDN 时,分别检查边缘证书与源站证书
网站接入了会终止 TLS 的 CDN、WAF 或负载均衡后,应分别检查访客入口和源站入口。
先通过第二节的域名检查命令,查看公网访问时返回的证书;再到前置服务控制台核对该域名绑定的证书、到期时间和部署状态。
如果要检查自己管理的源站,可指定源站 IP,同时保留正确的 SNI:
origin_ip='203.0.113.10'
openssl s_client -connect "${origin_ip}:443" \
-servername "$domain" </dev/null |
openssl x509 -noout -subject -issuer -dates \
-serial -fingerprint -sha256 -ext subjectAltName
203.0.113.10 是文档示例地址,必须替换为真实源站地址。源站如果限制了访问来源,应在有权限且可以访问源站的网络中检查。
还可以使用 curl 验证指定源站的 HTTPS 响应:
curl --noproxy '*' \
--resolve "${domain}:443:${origin_ip}" \
--connect-timeout 10 --max-time 20 \
-v -o /dev/null "https://${domain}/"
这条命令将连接定向到指定 IP,同时保留域名对应的 SNI、HTTP Host 和证书主机名校验。--noproxy '*' 用于避免本次请求被环境中的代理配置转发。
不要把它改成“访问 https://IP,再手动添加 Host 请求头”:TLS 握手发生在 HTTP 请求之前,仅修改 Host 无法完成同样的证书选择与校验。
源站如果使用仅受 CDN 信任的 Origin CA 证书,本地 curl 可能因缺少对应信任根而报错。此时应按所用服务的要求验证源站信任链;不要把添加 -k 后能访问,当成证书验证通过。
更新源站证书不会自动替换 CDN 的边缘证书,清理网页缓存也不会完成证书部署。 两个入口应按各自的证书配置和状态分别验收。

六、只有部分用户看到旧证书,检查多个访问入口
如果自己访问正常,其他人仍看到旧证书,或者不同网络下结果不一致,继续检查域名是否指向多个入口。
安装了 dig 时,可以查看当前解析器返回的 A 和 AAAA 记录:
dig +short "$domain" A
dig +short "$domain" AAAA
重点排查:
- 多台服务器是否只更新了其中一台。
- IPv4 入口已更新,IPv6 入口是否仍在使用旧证书。
- 是否还存在旧的负载均衡监听器或历史回源节点。
- DNS 刚调整后,部分解析器是否仍在缓存旧记录。
对于自己管理的每个入口,重复第五节的“指定 IP 并保留 SNI”检查。指定 IPv6 地址时,在地址外加方括号:
openssl s_client -connect '[2001:db8::10]:443' \
-servername "$domain" </dev/null |
openssl x509 -noout -dates -fingerprint -sha256
2001:db8::10 同样是文档示例地址。若域名接入 CDN,解析结果通常是 CDN 节点,源站列表应从自己的部署记录或控制台确认,不能把解析出的节点地址直接当成源站地址。
DNS 缓存可能让访问继续到达旧服务器,但它不会直接缓存证书。先确认连接落到了哪里,再处理对应节点。
七、常见结果怎么判断?
| 检查结果 | 优先处理方向 |
|---|---|
| 配置引用的本地文件仍是旧证书 | 核对续期是否完成、证书名称和部署路径 |
| 本地是新证书,同一源站仍返回旧证书 | 检查 Nginx 实例、重载日志与证书选择 |
| 源站正常,CDN 入口仍显示旧证书 | 检查边缘证书绑定、有效期和部署状态 |
| IPv4 正常,IPv6 返回旧证书 | 更新 IPv6 对应入口的证书配置 |
| 返回的是其他域名的证书 | 检查 SNI、server_name 和默认站点 |
| 证书已更新,仍提示不安全 | 检查域名覆盖范围、证书链、客户端时间和信任状态 |
完成调整后,还应从外部终端验证实际访问域名:
curl --noproxy '*' --connect-timeout 10 --max-time 20 \
-v -o /dev/null "https://${domain}/"
确认没有绕过证书校验,TLS 验证通过,且 HTTP 响应符合站点预期。如果发生跳转,还要检查最终落地的域名。
1. 指纹不同,就一定有一份是旧证书吗?
不一定。CDN 与源站可以使用不同证书;同时配置 RSA 和 ECDSA 证书时,不同客户端也可能选用不同证书。应在明确入口和证书类型后,分别与该入口预期部署的证书比对。
2. 自动续期成功,为什么下次还会出现问题?
需要确认续期后的部署流程是否完整,包括文件更新、服务重载及线上检查。如果使用 Certbot 的自定义流程,可以通过部署钩子在成功续期后执行所需动作,并检查钩子的执行结果。不要只监控续期命令是否返回成功。
3. 证书验证通过了,但网站出现 502 怎么办?
这时应继续检查反向代理和应用服务。可以参考本站的《Nginx 出现 502 Bad Gateway 怎么办?常见原因与排查教程》,排查上游进程、监听端口和代理配置。
八、结语
处理 SSL 证书更新后仍显示旧证书的问题,关键是把“文件已更新”和“访问入口已使用新证书”分别验证。
先记录线上返回的证书指纹与有效期,再核对配置引用的本地文件;确认服务成功加载后,分别检查 CDN、源站及 IPv4/IPv6 等实际入口。
日常维护时,把每个域名的证书位置、续期方式、部署动作和外部检查结果记录下来,并对实际访问入口设置到期监控,才能及时发现“续期成功,但部署没有完成”的问题。








