TT Lab
开始
学习 学习路径 课程

证书已经续期,浏览器却还显示旧证书

续期了,发出去的仍是旧证书

在 TT Lab 中继续学习

目标

针对只在启动时读取一次证书的 HTTPS 服务器重现续期事故,并编写两个脚本,用来监控服务器所发出的证书,而不是磁盘上的证书。

为什么重要

续期工具修改文件,服务器发出的是内存。如果其间没有重启,“续期成功”的日志和“即将到期”的告警就会同时为真。素材服务器 /opt/app/tlsserve.py 是只调用一次 load_cert_chain 的 Python HTTPS 服务器,和大多数实际的服务器一样,文件改变了也不会重新读取。本实验的监控脚本,要对评分器另外启动的服务器接受双向(同一文件 FRESH,不同文件 STALE)检查。

步骤

  1. 创建 /root/renew/ca.key、/root/renew/ca.crt(CN=Lab Root CA)、/root/renew/server.key,以及由 CA 签名的有效期 3 天的 /root/renew/v1.crt(SAN DNS:www.lab.internal)。
  2. 把 v1.crt 复制为 /root/renew/live.crt,把 server.key 复制为 /root/renew/live.key,然后启动 python3 /opt/app/tlsserve.py --cert /root/renew/live.crt --key /root/renew/live.key --port 8443。把用 openssl s_client 取回的证书的 serial= 这一行保存到 /root/renew/02-served.txt。
  3. 用同一把密钥签发有效期 30 天的 /root/renew/v2.crt,并覆盖到 live.crt(这是续期工具所做的事)。不要重启服务器。
  4. 再次用 s_client 把 serial= 保存到 /root/renew/04-served.txt,把 curl -sk https://127.0.0.1:8443/ 的正文保存到 /root/renew/04-body.txt。磁盘上必须是 v2,而服务器必须仍是 v1。
  5. 创建 /root/renew/certdiff.sh <인증서파일> <host:port>(占位符依次为证书文件、host:port)。如果磁盘文件与服务器所发证书的 SHA-256 指纹相同,就输出 FRESH 并以 0 结束;如果不同,就输出 STALE 并以 1 结束。把针对 live.crt 和 127.0.0.1:8443 运行的输出保存到 /root/renew/05-detect.txt。
  6. 结束服务器后重新启动,把 s_client 的 serial= 保存到 /root/renew/06-served.txt。
  7. 创建 /root/renew/servedcheck.sh <host:port> <초>(占位符依次为 host:port、秒数)。如果服务器所发证书在该秒数内到期,就输出 EXPIRING 并以 1 结束,否则输出 OK 并以 0 结束。把用 127.0.0.1:8443 604800 运行的输出保存到 /root/renew/07-monitor.txt。
  8. 在 /root/renew/08-report.md 中写下 v1 和 v2 的序列号、让服务器读取新文件的方法,以及监控为什么必须看服务器所发的证书,而不是磁盘。

参考

CA 与 3 天有效的 v1

在 /root/renew/ 中创建 ca.key、ca.crt(CN=Lab Root CA)、server.key,以及 3 天有效的 v1.crt(SAN DNS:www.lab.internal)。

与上一个模块的顺序相同——CA 自签名、带 SAN 的 CSR、用 x509 -req 签名(-copy_extensions copy)。CSR 在第 3 步还要再用,所以请留作 server.csr。

读取服务器所持有的证书

把 v1.crt 复制为 live.crt,把 server.key 复制为 live.key,在 8443 上启动 tlsserve.py,并把用 s_client 取回的 serial= 这一行保存到 /root/renew/02-served.txt。

服务器用 nohup 放到后台,日志输出到 /root/renew/server.log。把 s_client 的全部输出交给 x509 -noout -serial,就会得到 serial= 这一行。

续期——覆盖文件

用同一把密钥签发有效期 30 天的 /root/renew/v2.crt,并覆盖到 live.crt。不要重启服务器。

重新对同一个 CSR 签名即可(-days 30)。serial 会重新编号,到期日会延后。cp v2.crt live.crt 就是续期工具所做的全部。

磁盘是 v2,服务器是 v1

把 s_client 的 serial= 保存到 /root/renew/04-served.txt,把 curl -sk https://127.0.0.1:8443/ 的正文保存到 /root/renew/04-body.txt。

服务器会继续发出启动时读取的内容。两个文件中都必须看到 v1 的 serial,才算重现了事故。curl 的 -k 是因为用的是自建 CA 而关闭验证,正文中有服务器自己报出的 serial。

比较磁盘与服务器的脚本

创建 /root/renew/certdiff.sh <인증서파일> <host:port>(占位符依次为证书文件、host:port)(相同则 FRESH、0,不同则 STALE、1),并把针对 live.crt 和 127.0.0.1:8443 的输出保存到 /root/renew/05-detect.txt。

要取得两个指纹——文件用 x509 -in 文件 -fingerprint -sha256,服务器则把 s_client 的输出交给 x509 -fingerprint -sha256。如果无法从服务器取得证书,返回 ERROR 并以 2 结束会比较好。评分器会用自己的服务器,分别运行同一文件和不同文件两种情形。

重启——服务器读取新文件

结束服务器后重新启动,把 s_client 的 serial= 保存到 /root/renew/06-served.txt。

用 pkill -f tlsserve.py 结束,再用同一条命令重新启动。启动时会重新读取 live.crt,所以这次必须出现 v2 的 serial。

监控服务器所发证书的到期

创建 /root/renew/servedcheck.sh <host:port> <초>(占位符依次为 host:port、秒数)(在该秒数内到期则 EXPIRING、1,否则 OK、0),并把 127.0.0.1:8443 604800 的输出保存到 /root/renew/07-monitor.txt。

用 x509 -out 把 s_client 取回的证书保存到临时文件,再使用 -checkend <秒数> 即可。不能去看磁盘上的 live.crt——评分器会给它自己那台持有 2 天有效证书的服务器设置 7 天窗口,看是否会出现 EXPIRING。

事故报告

在 /root/renew/08-report.md 中写下 v1 和 v2 的序列号、让服务器读取新文件的方法,以及监控为什么必须看服务器所发的证书。

两个 serial 请用 -serial 从 v1.crt、v2.crt 中提取并原样写入。如果写进了“重启”一词和 's_client',评分器就能找到结论。