给网站安装免费的通配SSL证书,轻松实现HTTPS并自动续签

2024-08-14 22:38:35 浏览数 (2)

出于安全考虑,现在大部分的网站都已经配置了SSL证书,直观的感觉就是现在大部分的网站都是HTTPS,而不是HTTP了。甚至,Chrome 从90版本开始,就已经是默认请求HTTPS:

Chromium系请求页面Chromium系请求页面

那么,我们个人在部署网站的时候,如何部署SSL,快速实现HTTPS呢?方法很多,个人觉得,使用acme.sh是一个很不错的工具。

acme.sh

acme.sh是一个用纯 Shell (Unix shell语言) 写成的ACME协议客户端,作为对比,acme协议是Let's Encrypt和其他CA机构使用的一种网络交互协议,用于自动验证网站/域名并颁发SSL/TLS证书。

acme.sh就是利用这个acme协议,使用单一的Shell脚本自动为网站颁发和续订SSL证书。主要特点和功能包括:

  • 纯Shell语言实现,无其他依赖,很容易安装和使用。
  • 支持多种操作系统,如Linux、macOS、Windows(需要Cygwin)等。
  • 支持www模式、独立模式、DNS模式来验证域名。可以自动通过API完成DNS记录验证。
  • 可以为单域名或泛域名(通配符)颁发证书。支持SAN证书。
  • 可以直接安装颁发的证书到Nginx或Apache服务器。
  • 默认每60天自动检查并自动续订证书。
  • 支持ECC加密算法颁发的证书。

上手非常简单,如果你的Linux命令熟练几分钟即可上手使用。

目前支持的CA机构和CA机构支持的功能:

CA

最大有效期(日)

ECC加密

域名数量限制

泛域名

IPv4

IPv6

过期日

IDN

Let's Encrypt

90

支持

100

支持

不支持

不支持

不支持

支持

ZeroSSL

90

支持

100

支持

不支持

不支持

支持

支持

Google

90

支持

100

支持

不支持

不支持

支持

不支持

Buypass

180

支持

5

付费

不支持

不支持

不支持

支持

SSL.com

90

支持

2

付费

不支持

不支持

不支持

支持

acme.sh 主要有部署SSL的方案非常多,不过我个人主要使用两种方案,也是我推荐的两种方案:

  • Web服务器验证: 使用Nginx验证网站的归属,实现证书签发验证。
  • DNS API验证: 使用DNS厂商的API,自动校验域名归属,实现证书签发和续签。

操作前提

本次的操作前提是什么呢?很简单:

  • 一台服务器并部署Nginx服务;推荐使用腾讯云轻量应用服务器、腾讯云CVM服务器,轻松部署Nginx服务、搭建Web。
  • 域名和DNS服务器;比如:腾讯云的DNSPod、Cloudflare。
腾讯云DNSPOD腾讯云DNSPOD

注意,目前 acme.sh 安装的证书,是存放在服务器上,如果是使用CDN;需要自行考虑证书的同步问题。或者直接使用腾讯云的下一代CDN: EdgeOne。有机会,我们介绍EdgeOne的方法。

如何安装

如何安装 acme.sh 呢?一条命令即可:

代码语言:bash复制
curl https://get.acme.sh | sh -s email=my@example.com # 换成自己的邮箱(最好是ZeroSSL账号)

国内服务器如果无法访问,可以克隆仓库后手动安装:

代码语言:bash复制
# 克隆仓库
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 的基础命令:

代码语言:bash复制
acme.sh -h
查看帮助查看帮助

而查看帮助内,比较常用的是:

代码语言:bash复制
acme.sh --list
查看acme.sh管理的域名查看acme.sh管理的域名

一些情况下,acme.sh 可能会报错,这个时候,优先尝试升级 acme.sh:

代码语言:bash复制
# 升级acme.sh
acme.sh --upgrade
# 开启acme.sh的自动升级
acme.sh --upgrade --auto-upgrade
# 关闭acme.sh的自动升级
acme.sh --upgrade --auto-upgrade 0
更新acme.sh更新acme.sh

其次是默认使用 ZeroSSL,如果你想切换默认的 CA ,可以:

代码语言:bash复制
# 切换默认的CA机构为 letsencrypt
acme.sh  --set-default-ca  --server letsencrypt
切换默认CA切换默认CA

除了默认的letsencrypt(Let’s Encrypt)和zerossl(ZeroSSL),默认配置下,还支持的CA选项:buypass(Buypass)、ssl.com(SSL.com)和google(Google Public CA)。

同时,如果你申请了很多域名,但是其中有的域名已经不再使用,需要进行删除操作时,可以使用命令:

代码语言:bash复制
acme.sh --remove -d example.com
删除不需要的域名删除不需要的域名

接下来,我们看看如何使用acme.sh申请SSL证书。

ZeroSSL

acme.sh在3.0开始,默认使用ZeroSSL:https://zerossl.com/

其实和原本的 Let's Encrypt 差不多,ZeroSSL 有一个可视化的界面,还是很不错的,可以直观查看 SSL 是否续期成功;但是有点尴尬的是,我绑定了多个通配域名后,ZeroSSL 的控制台上,还是空空如也,可能 ZeroSSL 的控制台目前还不支持 acme.sh 的通配符展示(也可能是我部署的时候,ZeroSSL 的服务器宕机了):

ZeroSSL 的后台ZeroSSL 的后台
Uptime 检测 ZeroSSL 的服务器状态Uptime 检测 ZeroSSL 的服务器状态

不过,不影响我们的使用,你还是可以用acme.sh --list看看Linux服务器上SSL证书的续期情况。

如果你在使用acme.sh的时候,在已经有ZerorSSL的情况下,可以直接进行绑定:

代码语言:bash复制
acme.sh  --register-account -m 「ZeroSSL邮箱」 --server zerossl
acme.sh登录acme.sh登录

当然,你也可以直接使用ZeroSSL的EAB:

代码语言:bash复制
acme.sh  --register-account  --server zerossl 
--eab-kid "你账号的kid" 
--eab-hmac-key "你账号的key"
使用EAB进行登录使用EAB进行登录

其中的kidkey可以在ZeroSSL的这里进行获取:

获取EAB获取EAB

如果你不想使用ZeroSSL,可以切换为letsencrypt

方式对比

acme.sh支持多种方法进行部署,不过常用的是两种:

  • HTTP验证: 通过在Web服务器上创建临时文件,让ACME服务器验证域名的控制权。acme.sh可以自动配置常见的Web服务器,如Apache和Nginx,以便进行HTTP验证。我们也可以使用acme.sh提供的命令来生成临时文件并在验证完成后进行清理。
  • DNS验证: 通过在DNS服务器上添加相应的DNS TXT记录来验证域名所有权。acme.sh官方提供了多个DNS服务提供商的支持,包括Cloudflare、GoDaddy、Aliyun等。其他第三方DNS也可以根据ACME协议进行对接,不过大部分的DNS服务厂商,其实acme.sh都已经支持了。

两个方法都是很快速的方法,从结果上出发,最的区别就是DNS验证可以签署通配域名,也就是签署顶级二级域名后,其顶级二级域名分割出的三级域名都可以使用这个证书。

举个例子: 你为顶级二级域名example.com签署通配域名*.example.com,那么a.example.comb.example.com都可以使用这个通配域名证书。但是,使用acme.sh签署通配域名证书,只能使用DNS验证的方式进行签署。

有点复杂有点复杂

接下来,我们就来分别演示。

HTTP验证签署

acme.sh 其实可以自动HTTP验证。也就是你的Web服务器已经配置的情况下,你可以选择acme.sh自动修改Web配置并验证;也可以手动自动配置,并使用acme.sh进行配置的验证。

本次使用Nginx服务器为例,Apache其实也差不多。

自动配置签署

自动部署配置,其实就是自动配置Web服务器(Nginx、Apache)的配置,创建验证文件;在验证成功后,下载并配置好SSL证书,需要手动配置HTTPS

首先,我们需要确保Nginx已经配置到环境变量内:

代码语言:nginx复制
# 查看Nginx的版本
nginx -v
已经安装了nginx,并且配置到环境变量已经安装了nginx,并且配置到环境变量

在配置之前,确保Nginx当前的配置是可用的状态:

代码语言:bash复制
$ 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

按道理,就可以使用官方的命令进行安装:

代码语言:bash复制
acme.sh  --issue  -d example.com  --nginx
acme.sh自动配置acme.sh自动配置

配置完成:

配置完成配置完成

配置的原理是怎么样呢?

首先,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服务器上创建一个目录:

代码语言:bash复制
# 创建目录,用存放acme.sh验证文件
mkdir -p /www/acme/.well-known/acme-challenge
# 授权给nginx所在的用户
chown -R www:www /www/acme

并且在Nginx上进行配置:

代码语言:nginx复制
location /.well-known/acme-challenge/ {
    alias /www/acme/.well-known/acme-challenge/;
}

重载Nginx的配置,使用acme.sh即可完成配置部署:

代码语言:nginx复制
# Nginx 重载配置
nginx -s reload
# 使用acme.sh验证配置
acme.sh --issue -d example.com -d www.example.com -w /www/acme

解释一下:

  • -d example.com: 指定主域名为example.com。
  • -d www.example.com: 指定附加域名为www.example.com,这将成为同一个证书的 Subject Alternative Name。
  • -w /www/acme: 指定校验域名所有权的网站根目录为/www/acme。acme.sh会在此目录下生成临时文件用来向CA验证域名所有权。

CA机构的验证API正常的情况下,签署的过程是很丝滑的:

签署过程很丝滑签署过程很丝滑

需要注意的是,我们设置的/.well-known/acme-challenge/目录配置不要删除,否则可能影响后续的SSL续签。

部署SSL证书

acme.sh配置已经部署完成了:

部署完成的状态部署完成的状态

我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:

代码语言:bash复制
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"

操作的效果:

操作效果操作效果

解释一下:

命令参数:

  • --install-cert:安装 SSL 证书。
  • -d www.example.com: 指定要安装证书的域名。
  • --key-file: 指定私钥文件的路径。
  • --fullchain-file: 指定包含证书链的 PEM 文件的路径。
  • --reloadcmd: 指定在安装/更新证书后重新加载Web服务器的命令。

之后就是设置Nginx的HTTPS了,这里不再赘述。

嘿嘿,很丝滑嘿嘿,很丝滑

DNS验证签署

acme.sh还可以使用DNS验证签署的方式,支持通配域名,配合DNS厂商的API,也可以实现自动续期:

代码语言:mermaid复制
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验证;同理,续期也是一样的。

DNS API KEY

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,其他厂商的别名和支持,可以查看:

  • acme.sh 官方文档: DNS官方支持列表以及API KEY获取
  • acme.sh 官方文档: DNS官方支持列表以及API KEY获取(补充)
acme.sh官方支持列表acme.sh官方支持列表
acme.sh官方对DNSpod的描述acme.sh官方对DNSpod的描述

如果你所使用的DNS,不在acme.sh的支持列表内,你可以尝试手动适配: https://github.com/acmesh-official/acme.sh/wiki/DNS-manual-mode

登录DNSpod的后台地址:https://console.dnspod.cn/

选择API密钥管理:

选择API密钥选择API密钥

之后,我们创建一个密钥:

创建一个密钥创建一个密钥

创建好的ID和Token密钥:

创建好的ID和Token密钥创建好的ID和Token密钥

环境变量

acme.sh会从环境变量内,读取所需要用到的DNS API地址。你可以直接临时使用:

代码语言:bash复制
export DP_Id="<id>"
export DP_Key="<key>"

只要你在后续使用acme.sh的--dns dns_dp前,没有重载环境变量,那么acme.sh会把这个环境变量写入~/.acme.sh/account.conf内:

acme.sh保存的账户acme.sh保存的账户

当然,我会直接写到环境变量内,其实都一样:

添加到zsh的环境变量内添加到zsh的环境变量内

签署证书

我们使用acme.sh进行签署和验证:

代码语言:bash复制
acme.sh --dns dns_dp --issue -d "example.com" -d "*.example.com" --server zerossl
使用acme.sh进行SSL的签署使用acme.sh进行SSL的签署

一点点小的报错“红字”是没有关系的;如果没什么问题,片刻的等待后,就可以得到证书内容:

得到证书内容得到证书内容

签署的过程是很丝滑的。

部署SSL证书

我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:

代码语言:bash复制
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"

操作的效果:

部署SSL到指定位置部署SSL到指定位置

之后就是设置Nginx的HTTPS了,这里不再赘述。最后网站的效果:

浏览器上查看网站的SSL证书有效性浏览器上查看网站的SSL证书有效性

END

好啦,本次的教程就到这里啦。其实acme.sh的原理是挺简单的,对DNS的API和CA接口进行操作;省去了用户自己造“轮子”的时间和精力。

其实一开始别人和我推荐 acme.sh 的时候,我其实是比较反感的,总觉得,脚本修改网站配置或者给出DNS的API Key,也不安全。但是可以直接用别人造好的“轮子”是真的方便,而且本身是开源项目,其实及时更新,一般也没什么问题。

嘿嘿嘿嘿

0 人点赞