出于安全考虑,现在大部分的网站都已经配置了SSL证书,直观的感觉就是现在大部分的网站都是HTTPS,而不是HTTP了。甚至,Chrome 从90版本开始,就已经是默认请求HTTPS:
那么,我们个人在部署网站的时候,如何部署SSL,快速实现HTTPS呢?方法很多,个人觉得,使用acme.sh是一个很不错的工具。
acme.sh是一个用纯 Shell (Unix shell语言) 写成的ACME协议客户端,作为对比,acme协议是Let's Encrypt和其他CA机构使用的一种网络交互协议,用于自动验证网站/域名并颁发SSL/TLS证书。
acme.sh就是利用这个acme协议,使用单一的Shell脚本自动为网站颁发和续订SSL证书。主要特点和功能包括:
上手非常简单,如果你的Linux命令熟练几分钟即可上手使用。
目前支持的CA机构和CA机构支持的功能:
CA | 最大有效期(日) | ECC加密 | 域名数量限制 | 泛域名 | IPv4 | IPv6 | 过期日 | IDN |
---|---|---|---|---|---|---|---|---|
Let's Encrypt | 90 | 支持 | 100 | 支持 | 不支持 | 不支持 | 不支持 | 支持 |
ZeroSSL | 90 | 支持 | 100 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
90 | 支持 | 100 | 支持 | 不支持 | 不支持 | 支持 | 不支持 | |
Buypass | 180 | 支持 | 5 | 付费 | 不支持 | 不支持 | 不支持 | 支持 |
SSL.com | 90 | 支持 | 2 | 付费 | 不支持 | 不支持 | 不支持 | 支持 |
acme.sh 主要有部署SSL的方案非常多,不过我个人主要使用两种方案,也是我推荐的两种方案:
本次的操作前提是什么呢?很简单:
注意,目前 acme.sh 安装的证书,是存放在服务器上,如果是使用CDN;需要自行考虑证书的同步问题。或者直接使用腾讯云的下一代CDN: EdgeOne。有机会,我们介绍EdgeOne的方法。
如何安装 acme.sh 呢?一条命令即可:
curl https://get.acme.sh | sh -s email=my@example.com # 换成自己的邮箱(最好是ZeroSSL账号)
国内服务器如果无法访问,可以克隆仓库后手动安装:
# 克隆仓库
git clone https://github.com/acmesh-official/acme.sh.git
# 进入仓库内
cd ./acme.sh
# 运行脚本
./acme.sh --install -m my@example.com # 换成自己的邮箱(最好是ZeroSSL账号)
为什么最好使用 ZeroSSL 的账号邮箱呢?很早之前,ZeroSSL 就买了
acme.sh
这个网站,所以,后来 amce.sh 切换默认的 CA 为 ZeroSSL 也是很正常的啦。而 ZeroSSL 申请 SSL ,需要预留邮箱。
在腾讯云的香港服务器安装成功:
之后,我们使用acme.sh -v
,就可以看到 acme.sh 的版本号:
如果 acme.sh 没有添加到环境变量内,可以进行手动添加:
在教程开始之前,我们看看 acme.sh 的基础命令:
acme.sh -h
而查看帮助内,比较常用的是:
acme.sh --list
一些情况下,acme.sh 可能会报错,这个时候,优先尝试升级 acme.sh:
# 升级acme.sh
acme.sh --upgrade
# 开启acme.sh的自动升级
acme.sh --upgrade --auto-upgrade
# 关闭acme.sh的自动升级
acme.sh --upgrade --auto-upgrade 0
其次是默认使用 ZeroSSL,如果你想切换默认的 CA ,可以:
# 切换默认的CA机构为 letsencrypt
acme.sh --set-default-ca --server letsencrypt
除了默认的letsencrypt(Let’s Encrypt)和zerossl(ZeroSSL),默认配置下,还支持的CA选项:buypass(Buypass)、ssl.com(SSL.com)和google(Google Public CA)。
同时,如果你申请了很多域名,但是其中有的域名已经不再使用,需要进行删除操作时,可以使用命令:
acme.sh --remove -d example.com
接下来,我们看看如何使用acme.sh申请SSL证书。
acme.sh在3.0开始,默认使用ZeroSSL:https://zerossl.com/
其实和原本的 Let's Encrypt 差不多,ZeroSSL 有一个可视化的界面,还是很不错的,可以直观查看 SSL 是否续期成功;但是有点尴尬的是,我绑定了多个通配域名后,ZeroSSL 的控制台上,还是空空如也,可能 ZeroSSL 的控制台目前还不支持 acme.sh 的通配符展示(也可能是我部署的时候,ZeroSSL 的服务器宕机了):
不过,不影响我们的使用,你还是可以用acme.sh --list
看看Linux服务器上SSL证书的续期情况。
如果你在使用acme.sh的时候,在已经有ZerorSSL的情况下,可以直接进行绑定:
acme.sh --register-account -m 「ZeroSSL邮箱」 --server zerossl
当然,你也可以直接使用ZeroSSL的EAB:
acme.sh --register-account --server zerossl \
--eab-kid "你账号的kid" \
--eab-hmac-key "你账号的key"
其中的kid
和key
可以在ZeroSSL的这里进行获取:
如果你不想使用ZeroSSL,可以切换为letsencrypt
。
acme.sh支持多种方法进行部署,不过常用的是两种:
两个方法都是很快速的方法,从结果上出发,最的区别就是DNS验证可以签署通配域名,也就是签署顶级二级域名后,其顶级二级域名分割出的三级域名都可以使用这个证书。
举个例子: 你为顶级二级域名example.com
签署通配域名*.example.com
,那么a.example.com
和b.example.com
都可以使用这个通配域名证书。但是,使用acme.sh签署通配域名证书,只能使用DNS验证的方式进行签署。
接下来,我们就来分别演示。
acme.sh 其实可以自动HTTP验证。也就是你的Web服务器已经配置的情况下,你可以选择acme.sh自动修改Web配置并验证;也可以手动自动配置,并使用acme.sh进行配置的验证。
本次使用Nginx服务器为例,Apache其实也差不多。
自动部署配置,其实就是自动配置Web服务器(Nginx、Apache)的配置,创建验证文件;在验证成功后,下载并配置好SSL证书,需要手动配置HTTPS。
首先,我们需要确保Nginx已经配置到环境变量内:
# 查看Nginx的版本
nginx -v
在配置之前,确保Nginx当前的配置是可用的状态:
$ nginx -t
nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/nginx.conf test is successful
按道理,就可以使用官方的命令进行安装:
acme.sh --issue -d example.com --nginx
配置完成:
配置的原理是怎么样呢?
首先,acme.sh会检测Nginx的配置文件地址。如果你的Nginx使用的是主config文件,引入子config(也就是:include /www/wwwConf/*.conf
这样的形式)也是支持的;根据你指定的域名,找到具体的server
配置片段所在的文件,将其备份。
之后,修改server
配置片段,主要的修改内容就是后续我们手动的配置;修改配置后,acme.sh会使用Nginx的nginx -t
检测配置的合法性,如果不合法,那么直接恢复备份终止脚本。
最后,在server
修改完成,并和CA校验成功后;签署SSL证书并还原Nginx备份。之后如果是acme.sh的续签,也是重新运行此过程。
那么如果你不想让acme.sh自动配置呢?我们可以自己配置。
手动配置的灵活性更高;自动配置签署和手动配置签署二选一就可以了。
手动配置,就是在Nginx上配置一个目录,使其acme.sh在Linux的服务器内写入CA机构下发的验证文件,通过Http可以访问到。
首先,在Linux服务器上创建一个目录:
# 创建目录,用存放acme.sh验证文件
mkdir -p /www/acme/.well-known/acme-challenge
# 授权给nginx所在的用户
chown -R www:www /www/acme
并且在Nginx上进行配置:
location /.well-known/acme-challenge/ {
alias /www/acme/.well-known/acme-challenge/;
}
重载Nginx的配置,使用acme.sh即可完成配置部署:
# Nginx 重载配置
nginx -s reload
# 使用acme.sh验证配置
acme.sh --issue -d example.com -d www.example.com -w /www/acme
解释一下:
CA机构的验证API正常的情况下,签署的过程是很丝滑的:
需要注意的是,我们设置的/.well-known/acme-challenge/
目录配置不要删除,否则可能影响后续的SSL续签。
acme.sh配置已经部署完成了:
我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:
acme.sh --install-cert -d www.example.com \
--key-file /www/ssl/www.example.com.key \
--fullchain-file /www/ssl/www.example.com.pem \
--reloadcmd "systemctl reload nginx"
操作的效果:
解释一下:
命令参数:
之后就是设置Nginx的HTTPS了,这里不再赘述。
acme.sh还可以使用DNS验证签署的方式,支持通配域名,配合DNS厂商的API,也可以实现自动续期:
sequenceDiagram
participant U as 用户服务器
participant A as acme.sh
participant DP as DNS提供商
participant CA as 证书机构
U->A: 签发证书
A->DP: 创建TXT记录
DP->A: 证书签发完成
A->CA: 请求签名
CA->A: 返回签名
A->U: TXT生效等待
U-->A: 续订证书
A->DP: 更新TXT记录
DP->A: TXT记录已更新
A->CA: 请求续订签名
CA->A: 返回续订签名
A-->U: 更新证书
从流程图就可以看出来,我们需要DNS添加TXT验证。 如果是自己添加DNS的TXT的验证,岂不是和以往差不多么?没错,acme.sh就是可以通过DNS厂商的API,自动添加TXT验证,在验证成功后,自动删除添加的TXT验证;同理,续期也是一样的。
acme.sh 需要使用DNS厂商的API,添加TXT记录地址,帮助CA签发机构验证我们对域名的所有权。而acme.sh操作DNS厂商的API,就需要API密钥鉴权。
acme.sh已经适配了多家DNS厂商的API,比如: Cloudflare,、DNSPod(腾讯)、Cloudxns, Godadd等等。我们就以DNSpod为例,看看如何操作。
DNSpod在acme.sh的别名是:dns_dp
,其他厂商的别名和支持,可以查看:
如果你所使用的DNS,不在acme.sh的支持列表内,你可以尝试手动适配: https://github.com/acmesh-official/acme.sh/wiki/DNS-manual-mode
登录DNSpod的后台地址:https://console.dnspod.cn/
选择API密钥管理:
之后,我们创建一个密钥:
创建好的ID和Token密钥:
acme.sh会从环境变量内,读取所需要用到的DNS API地址。你可以直接临时使用:
export DP_Id="<id>"
export DP_Key="<key>"
只要你在后续使用acme.sh的--dns dns_dp
前,没有重载环境变量,那么acme.sh会把这个环境变量写入~/.acme.sh/account.conf
内:
当然,我会直接写到环境变量内,其实都一样:
我们使用acme.sh进行签署和验证:
acme.sh --dns dns_dp --issue -d "example.com" -d "*.example.com" --server zerossl
一点点小的报错“红字”是没有关系的;如果没什么问题,片刻的等待后,就可以得到证书内容:
签署的过程是很丝滑的。
我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:
acme.sh --install-cert -d www.example.com \
--key-file /www/ssl/www.example.com.key \
--fullchain-file /www/ssl/www.example.com.pem \
--reloadcmd "systemctl reload nginx"
操作的效果:
之后就是设置Nginx的HTTPS了,这里不再赘述。最后网站的效果:
好啦,本次的教程就到这里啦。其实acme.sh的原理是挺简单的,对DNS的API和CA接口进行操作;省去了用户自己造“轮子”的时间和精力。
其实一开始别人和我推荐 acme.sh 的时候,我其实是比较反感的,总觉得,脚本修改网站配置或者给出DNS的API Key,也不安全。但是可以直接用别人造好的“轮子”是真的方便,而且本身是开源项目,其实及时更新,一般也没什么问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。