在申请 ssl 时,大部分平台都会存在或多或少的限制,比如国内平台的 亚洲诚信 ,该平台可以一次性申请双域名有效期为一年的证书,或者短期的通配符证书
但是这些都不好用,一是申请麻烦,而是各种平台策略问题,比如 腾讯云只允许申请 50 个免费证书(20 个外部证书,30 个仅限腾讯云托管的域名的证书),并且不允许续期,只能手动吊销后重新申请。整过过程十分繁琐,还需要各种扫码验证,吊销还需要 dns 记录认证,非常麻烦,已经远超手动搭建续期机器人的人力成本了。
补充
2023.12.29
近期本人遇到了 ZeroSSL 的小问题(https://github.com/acmesh-official/acme.sh/issues/3850、https://github.com/acmesh-official/acme.sh/issues/3842),经过查找答案,不删干净原来的无用解析,会报 504 ,因此在申请时可通过附加 --server letsencrypt
字段来更换 CA 服务器 (参考:https://github.com/acmesh-official/acme.sh/wiki/Change-default-CA-to-ZeroSSL)
也可以直接将默认 CA 服务器设置为 letsencrypt 或其他(下文)
acme.sh --set-default-ca --server letsencrypt
当然也可以使用其他服务器将 server 字段的值调整为下表中的 “CA 服务器”, acme.sh 支持的各大服务器汇总
Let’s Encrypt | Buypass | ZeroSSL | SSL.com | Google Public CA | |
CA 服务器 | letsencrypt | buypass | zerossl | ssl.com | |
有效期 | 90天 | 180天 | 90天 / 365天 | 90天 | 90天 |
多域名 | 支持 | 最多5个 | 支持 | 收费 | 支持 |
泛域名 | 支持 | 支持 | 支持 | 收费 | 支持 |
错误限制 | 5次/时 | 5次/时 | 无 | 无 | 无 |
SSL管理 | 无 | 无 | 有 | 有 | 无 |
ECC 证书链 | 有 | 无 | 有 | 无 | 有 |
客户支持 | 论坛 | 收费 | 收费 | 收费 | 收费 |
安装 acme.sh 脚本
访问 acme.sh 的主页 https://github.com/acmesh-official/acme.sh/ ,可以清楚的看到非常详细的教程
# 使用 curl
curl https://get.acme.sh | sh
# 使用 wget
wget -O - https://get.acme.sh | sh
如果是 centos 系统,可以直接运行 yum update ca-certificates
来快速安装
当然,官方建议在安装时,携带 -s email=my@example.com
的参数
如 curl https://get.acme.sh | sh -s email=my@example.com
更多参数详见官方文档相关内容部分(https://github.com/acmesh-official/acme.sh/wiki/How-to-install#4-advanced-installation)
除此之外,也可以直接使用在线脚本或者手动克隆仓库来安装
# 在线脚本
curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m my@example.com
wget -O - https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m my@example.com
# 克隆仓库安装
git clone --depth 1 https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
程序默认安装到用户目录下,请自行配置环境变量,或直接在程序安装目录下操作
生成证书
acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证
如果你的域名托管服务商支持使用 API ,那么你就可以享受自动添加 DNS 记录,请将相关必要信息配置在变量中,具体变量详见:https://github.com/acmesh-official/acme.sh/wiki/dnsapi ,内有非常多平台的配置教程,本文以 Cloudflare 为例
export CF_Key="cloudflare 中查看你的 key"
export CF_Email="你的 cloudflare 邮箱"
当然,全局 key 太危险了,直接使用肯定是不现实的,所以我们使用区域 API (要是区域API要再能设置只能增加 / 修改指定的解析条目就好了)
如果你生成的区域 API 只能编辑一个域名的 DNS
export CF_Zone_ID="域名 ID" # 该区域 ID 可以通过 Cloudflare 仪表板在区域概述页面的右侧边栏中找到
export CF_Token="区域 API"
如果你生成的区域 API 可以编辑多个域名的 DNS
export CF_Account_ID="账号 ID" # 该帐户 ID 可以通过 Cloudflare 仪表板找到,作为登录时 URL 的末尾,或者在任何区域的概述页面上的右侧边栏中区域 ID 下方找到,也可以直接在 Url 上找到
export CF_Token="区域 API"
如果你域名托管的平台不支持使用 API 来配置解析记录,或者你不想要程序自动配置,可以选择手动配置解析记录,具体请参考 https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode
在申请正式证书前可以先测试一下(可选)
# 使用文件验证
acme.sh --issue --server letsencrypt --test -d www.gov.cn -w /www/wwwroot/www.gov.cn --keylength ec-256
# 使用 Dns
acme.sh --issue --server letsencrypt --test -d acme.sh --dns dns_cf --keylength ec-256
可以添加 --dnssleep <秒数>
参数,来等待 dns 解析生效,这对于托管在国内 dns 服务商的域名很有必要
如果需要申请通配符域名,如 *.example.com
那么需要在星号的前面加上反斜杠来转义,或者使用引号包含你传入的域名
本文均以 ECC
证书为例,因为时至今日,实在没什么理由不用它。ECC
证书的主要优势在于它的 Keysize 更小,意味着同等大小下安全性的提升和加密解密速度的加快。如 ECC-256bit 的强度大约相当于 RSA-3072bit,当然,有人说 ECC 证书握手会明显更快,这我觉得就有些夸张了,因为 RSA 握手也没有太慢,就算有差别应该也是毫秒级,很难直接感知。另外,如果有些网站确实需要兼容某些古老设备的,那也还是请按需选择RSA
证书。
这里申请的是测试证书,没办法直接用的,只是用来证明你的域名、配置全都正确。仔细观察,你会发现给你发证书的域名是 https://acme-staging-v02.api.letsencrypt.org
,仅用于测试。如果出错了,可以加上 --debug
参数,使用调试模式进行申请。测试证书不需要删除,它会自动被正式证书覆盖。
申请正式证书
在申请前,请先删除 --test
参数,然后加上 --force
参数, --force
参数的意思就是,在现有证书到期前,手动(强行)更新证书。上一步我们在测试服务器申请到的证书,但是它本身是尚未过期的,所以需要用到这个参数。
# 使用文件验证
acme.sh --issue -d www.gov.cn -w /www/wwwroot/www.gov.cn --keylength ec-256 --force
# 使用 Dns 验证
acme.sh --issue -d www.gov.cn --dns dns_cf --keylength ec-256 --force
安装证书
这一步是可选的,证书已经生成在了 acme.sh 的程序目录中,但是需要注意,不要直接让 nginx / apache 的配置文件使用这下面的文件。这里面的文件都是内部使用的,而且目录结构可能会变化。
正确的使用方法是使用 --install-cert
命令,并指定目标位置,然后将证书文件复制到相应的位置
# apache
acme.sh --install-cert -d example.com \
--cert-file /path/to/certfile/in/apache/cert.pem \
--key-file /path/to/keyfile/in/apache/key.pem \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 force-reload"
# nginx
acme.sh --install-cert -d example.com \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"
你也可以在申请的时候直接配置相关参数,如
# nginx
acme.sh --issue -d www.gov.cn --dns dns_cf \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"
# apache 同理
# ...
需注意, nginx 用的是 service nginx force-reload
,不是 service nginx reload
,据测试,reload
并不会重新加载证书
Nginx的配置 ssl_certificate
使用 /etc/nginx/ssl/fullchain.cer
,另外 /etc/nginx/ssl/<domain>.cer
,否则 SSL Labs 的测试会报错 Chain issues Incomplete
。
--install-cert
命令可以输入很多参数,来指定目标文件。并且可以指定 reloadcmd ,当证书更新以后, reloadcmd 会被自动调用,让服务器生效。
详细参数请参考:https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc
这里指定的所有参数都会被自动记录下来,并在以后证书自动更新以后,被再次自动调用。
自动更新和续签
开启 acme.sh 的自动升级
acme.sh --upgrade --auto-upgrade
移除域名证书自动续签
acme.sh --remove -d www.gov.cn -d example.com
参考文献
https://github.com/acmesh-official/acme.sh/wiki
https://github.com/acmesh-official/acme.sh/wiki/dnsapi
https://suzuhafan.com/tutorials/acmesh-use-cloudflare-to-create-ssl.html
https://juejin.cn/post/6989892297907240973
https://xtls.github.io/document/level-0/ch06-certificates.html#_6-2-%E5%AE%89%E8%A3%85-acme-sh