又双叒叕到期了?拿什么拯救你的HTTPS证书有效期
前言
根据 CA/B 论坛的提案,HTTPS 证书的最长有效期已经于 2026 年 3 月 15 日起,缩短至最长 200 天。并于 2027 年缩短至最长 100 天,进而在 2029 年缩短至最长 47 天。HTTPS 证书有效期超过一年的时代已经彻底一去不复返了!
有效期为 200 天,意味着每半年需要更新一次证书;有效期为 100 天,意味着每三个月需要更新一次证书;有效期为 47 天,意味着每个月需要更新一次证书。届时,唯有自动更新证书,才能保证网站的证书始终有效。
本文将介绍一些与 HTTPS 证书相关的理论知识,旨在帮助读者轻松理解 HTTPS 证书基础原理,以及如何使用 acme.sh 自动更新证书,只对如何操作感兴趣的读者也可以直接跳到最后。
一些概念
证书(Certificate),也叫电子身份证书,和我们人类世界的身份证功能是一样的,用于证明自己的身份。SSL 证书中包含网站域名的信息。早期证书使用 Common Name(CN)字段存储域名,但现代证书已改用 SAN(Subject Alternative Name)字段,浏览器也以 SAN 为准进行域名验证,CN 字段已被 RFC 5280 标记为废弃。
CA(Certificate Authority):即证书颁发机构,负责对证书申请者进行身份验证,验证通过后,向申请者颁发证书。证书颁发机构也可以对已生效的证书进行撤销。
CA/B 论坛,其中 CA 是证书颁发机构,B 是浏览器,成员包括各大 CA 如 Digicert,各大浏览器厂商如 Google、微软、苹果等公司。
证书申请&颁发流程
- 生成密钥对(Key Pair),包含公钥和私钥
- 申请方创建证书请求文件(Certificate Request File,CSR),包含申请方的公钥、域名等信息
- 申请方将 CSR 提交给 CA,CA 会验证申请方的身份,验证通过后,向申请方颁发证书
- 申请方收到证书后,将证书和私钥安装到服务器上
当我们使用浏览器访问一个 https 站点时,在建立连接的过程中服务器会将证书发送给浏览器,浏览器会检查证书是否有效,如果证书无效,浏览器会展示一个警告信息来阻止用户访问,如下图:

浏览器是怎么判断证书是否有效的呢?
它会对证书的以下几个方面进行检查:
- 证书的 SAN 字段是否包含当前访问的域名
- 证书是否由受信任的 CA 签发
- 当前时间是否在证书有效期内
- 证书是否被撤销
还有一个问题是浏览器是如何判断证书是可信任的呢?这里有个”信任链”的概念。浏览器通过信任链机制验证证书:操作系统内置了一些可信 CA 的根证书,由这些根证书签发的中间 CA 证书也被信任,最终由中间 CA 签发的网站证书也就被信任。
所有的证书都是有有效期的,包括系统中内置的 CA 根证书。所以如果我们在自己电脑上安装一个比较老的操作系统,像 Windows XP,你会发现当年用的好好的系统,现在竟然大部分网站都打不开了,这是因为 Windows XP 中内置的 CA 根证书已经过期了,过期了就变成无效的 CA 证书,由这种无效的 CA 证书签发的 HTTPS 证书也就不可信了。
CA 是如何验证申请方身份的?
我们都知道 https 是一种安全协议,它的安全有一个前提,就是所有的 CA 在颁发证书的时候,必须合法合规。也就是说,只能给百度颁发 baidu.com 的证书,而不是随便一个人要申请 baidu.com 的证书都能申请到。就好比在现实世界,别人可以办一张上面写有你的身份信息的身份证是一种多么可怕的事情。基于这个前提,使用 https 就解决了中间人攻击的问题。
要进行中间人攻击,中间人需要分别和客户端和目标服务器建立连接,但是中间人没有服务器证书的私钥,所以提供不了有效的服务器证书,这时浏览器就会提示访问的链接不安全。当浏览器出现这种提示时,为了保护自己的信息安全,应立刻停止访问该网站。
CA 对申请人的身份进行验证,从低到高,有这几种验证方式:
DV(Domain Validation)
DV 是最基本的验证方式,因为证书是颁发给域名的,所以要验证域名的所有权。验证域名的所有权的方法也很简单,比如:
- CA 让申请方为该域名添加一个指定的 DNS 记录,如果申请方能添加上,说明申请方有该域名的所有权
- CA 让申请方在该域名指向的服务器上添加一个文件,如果申请方能添加上,也能说明申请方有该域名的所有权
OV(Organization Validation)
OV 建立在 DV 的基础上,并增加验证申请人是组织的合法代表。通常是通过联系该组织官网上的电话或邮箱来验证。
EV(Extended Validation)
EV 建立在 DV 的基础上,并增加比 OV 更严格的企业验证。比如 Digicert EV SSL 和 OV 相比,企业验证只能使用企查查、百度地图、114查号台电话,不能使用邮箱,并且不支持使用官网登记的联系方式。需要注意的是,早期浏览器会对 EV 证书显示绿色的地址栏或锁图标,但 Chrome 于 2019 年移除了这一特性,Firefox 随后也跟进,现在 EV 证书在浏览器 UI 上与 DV/OV 证书已无明显区别。
一些历史
回想十几年前,部署 HTTPS 的网站还是很少的,除了一些购物、银行等对安全级别要求高的网站,其他大部分网站都是 HTTP 的。那时候申请 HTTPS 证书还是挺贵的,所以大部分网站就直接 HTTP 裸奔,还有一种方式就是使用自签名证书。最有名的就说 12306,这个网站刚上 HTTPS 的时候,就是使用的自签名证书,所以那时候每次在电脑上访问 12306,首页上都会提示用户安装 12306 的 CA 根证书。
这里简单介绍一下自签名证书。自签名证书就是自己生成一个 CA 证书,然后用自己的 CA 证书来颁发 HTTPS 证书。因为用户的操作系统中并没有内置自己生成的这个 CA 证书,所以要想让用户的浏览器信任自己的 HTTPS 证书,就需要先让用户把自己生成的 CA 证书安装到操作系统中。
把自签名的 CA 根证书安装到自己的操作系统中的这种做法是有风险的,因为我们无法保证这个 CA 不乱颁发证书。回到我们上面说的中间人攻击那里,一旦这个 CA 为可以劫持我们网络的中间人颁发了证书,我们的浏览器就会信任这个中间人的证书,从而达到中间人攻击的效果。
那么,正规 CA 就一定能保证不乱颁发证书吗?正规 CA 确实可以这样做,但这无异于自掘坟墓。因为 CA 本身就是靠信用吃饭的,如果一个 CA 不讲信用,各大操作系统就不再会内置它的 CA 根证书,这样这个 CA 也就在这个行业混不下去了。
到了 2015 年后,Let’s Encrypt 横空出世,通过 Let’s Encrypt 可以申请免费的 HTTPS 证书,HTTPS 证书的价钱才被打下来,到现在我们在阿里云、腾讯云上都可以轻松的申请到免费的 HTTPS 证书。而且现在绝大多数网站都已经升级到 HTTPS,而 HTTP 的网站几乎见不到了。
ACME 协议
站在安全的角度讲,证书的有效期越短越安全,因为每次颁发证书都需要认证,所以短的有效期代表刚刚认证过,同时有问题的证书也会很快到期。
但是有效期变短给网站的运维带来了新的问题,频繁申请更新证书带来了额外的工作量。好消息是 Let’s Encrypt 自研并开源了 ACME(Automatic Certificate Management Environment) 协议,用于自动申请和更新 HTTPS 证书。通俗点说,就是只要 CA 支持 ACME 协议,那我们就可以使用 ACME 工具把证书申请流程自动化。
acme.sh
acme.sh 就是一个基于 ACME 协议的工具,它的使用很简单。由于现实环境中存在不同的服务器配置和 DNS 服务商,本部分内容无法覆盖所有场景,但掌握了核心原理后,相信聪明的读者可以根据自身情况灵活调整。
安装 acme.sh
# 这里的邮箱要换成自己的邮箱哦
curl https://get.acme.sh | sh -s email=my@example.com
需要注意的是,上述命令需要访问 GitHub,如果你的网络不能访问 GitHub,可以使用下面的命令代替(改用 Gitee 源):
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
安装命令会把 acme.sh 安装到 ~/.acme.sh 目录下,为了方便后续可以在任意目录执行 acme.sh,可以设置一个环境变量别名alias acme.sh=~/.acme.sh/acme.sh
申请签发证书
我们这里以 DNS 验证模式为例,除了 DNS 验证模式外,acme.sh 还支持 HTTP 验证模式。
在开始之前,我们需要先在自己的 DNS 服务商那里申请 api key,有了 api key 后,acme.sh 就可以自己帮我们处理设置 DNS 记录这种事了。
分别以 Cloudflare 和 DNSPods 为例:
Cloudflare
如果你的 DNS 服务商是 Cloudflare,你需要先在 Cloudflare 上申请 API 令牌、账户 ID、域名 Zone ID,然后在命令中替换掉对应的变量。
export CF_Token="替换为CF令牌"
export CF_Account_ID="替换为CF账户ID"
export CF_Zone_ID="替换为CF域名ZoneID"
Cloudflare 签发证书:
acme.sh --issue \
-d domain.com \
-d *.domain.com \
--dns dns_cf \
--keylength ec-256
DNSPods 设置 api key
如果你的 DNS 服务商是 DNSPods,你需要先在 DNSPods 上申请 API 密钥,然后在命令中替换掉对应的变量。
export DP_Id="替换为DNSPods ID"
export DP_Key="替换为 DNSPods 提供的 API 密钥"
DNSPods 签发证书:
acme.sh --issue \
-d domain.com \
-d *.domain.com \
--dns dns_dp \
--keylength ec-256
安装证书
证书签发后,下一步就是安装到 Web 服务器上了,这里以 Nginx 服务器为例,假设我们的 Nginx 安装在 /etc/nginx 目录下,证书和私钥文件分别放到/etc/nginx/cert/yourdomain.crt和/etc/nginx/cert/yourdomain.key。
先修改 Nginx 的配置文件,可参考如下配置:
server {
listen 443 ssl;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/nginx/cert/yourdomain.crt;
ssl_certificate_key /etc/nginx/cert/yourdomain.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
location / {
root /var/www/html;
index index.html index.htm;
}
}
我们需要注意ssl_certificate和ssl_certificate_key就是我们上面定好的证书和私钥文件路径。
接下来就是把签发好的证书安装到 Nginx 上了:
acme.sh --install-cert -d domain.com \
--key-file /etc/nginx/cert/yourdomain.key \
--fullchain-file /etc/nginx/cert/yourdomain.crt \
--reloadcmd "systemctl reload nginx"
这个命令中的几个参数介绍一下:
key-file: 私钥文件会被部署到这个位置fullchain-file: 证书文件会被部署到这个位置reloadcmd: 重启 Web 服务器的命令,证书部署完后,acme.sh 会自动执行这个命令帮我们重启 Web 服务器
自动续期机制
acme.sh 安装后会自动在系统中创建一个 cron 定时任务,默认每天检查一次证书是否需要更新。你可以通过以下命令查看:
crontab -l
你应该能看到类似这样的定时任务:
0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null
当证书距离过期时间少于 30 天时,acme.sh 会自动执行续期流程,重新申请证书并执行安装命令中指定的 reloadcmd。
常用命令
# 查看已颁发的所有证书
acme.sh --list
# 查看某个证书的详细信息
acme.sh --info -d domain.com
# 手动触发续期检查
acme.sh --cron
# 强制续期某个证书
acme.sh --renew -d domain.com --force
# 查看续期日志
cat ~/.acme.sh/acme.sh.log
总结
HTTPS 证书有效期的不断缩短已成定局,手动管理证书的方式将难以为继。幸运的是,ACME 协议和 acme.sh 等工具让我们可以轻松实现证书的自动申请和续期。建议所有网站运维人员尽早配置自动续期机制,以应对即将到来的 100 天甚至 47 天证书有效期限制。
好了,朋友们,感谢你读到这里,同时也恭喜你没用的知识又增加了。欢迎您对本文进行评论、转发、点赞,您的支持是我创作最大的动力!