欢迎光临
我们一直在努力

SSL 证书更新后仍显示旧证书怎么办?Nginx 与 CDN 排查教程

证书管理工具已经提示续期成功,服务器里也能看到新证书,但打开网站时,浏览器仍然显示旧的到期时间,甚至继续提示证书过期。这是维护 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 站点时,省略它可能拿到默认站点的证书。

这条命令用于查看对端发送的证书,能打印信息不代表信任验证已经通过。检查时保留终端中的错误提示;如果未能读到证书,应先处理连接失败或握手失败。

使用 OpenSSL 和 SNI 查看网站证书有效期与 SHA-256 指纹

三、核对 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 是否成功加载新证书

本节命令适用于通过系统软件包安装,并由 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 连接核对证书。已有浏览器连接可能继续使用原来的会话,仅刷新页面不适合作为唯一验收方法。

检查 Nginx 配置、重载服务并查看相关日志

五、接入 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 的边缘证书,清理网页缓存也不会完成证书部署。 两个入口应按各自的证书配置和状态分别验收。

使用 curl resolve 指定源站 IP 并保留域名证书校验

六、只有部分用户看到旧证书,检查多个访问入口

如果自己访问正常,其他人仍看到旧证书,或者不同网络下结果不一致,继续检查域名是否指向多个入口。

安装了 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 等实际入口。

日常维护时,把每个域名的证书位置、续期方式、部署动作和外部检查结果记录下来,并对实际访问入口设置到期监控,才能及时发现“续期成功,但部署没有完成”的问题。

赞(0)
未经允许不得转载:莱卡云 » SSL 证书更新后仍显示旧证书怎么办?Nginx 与 CDN 排查教程