如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书

Linux2022-05-27
如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书-下一朵云
图1 Let’s Encrypt

acme.sh的github项目链接:https://github.com/acmesh-official/acme.sh

Let’s Encrypt只支持DV证书的签发,也就是通过验证域名所有权,然后签发该域名的证书。它支持两种验证方式,一种是通过HTTP的方式验证,另一种是通过DNS的方式验证,而今天要讲的就是第二种方式。

1.获取阿里云DNS修改的Accesskey

在签发证书前需要准备阿里云账户的Accesskey,打开以下地址并创建AccessKey即可:

https://usercenter.console.aliyun.com/#/manage/ak

如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书-下一朵云
图2 Accesskey 管理

注意!阿里云支持子账户功能,为了提高安全性,请参考阿里云的文档,创建子账户后再创建API key,但这不是必须操作的。

创建完成后将AccessKey ID与Access Key Secret记下来备用。

2.安装acme.sh

1)安装很简单,命令如下,把 acme.sh 安装到你的 home 目录下:~/.acme.sh/

cd ~
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m  my@example.com

说明:my@example.com 替换为你自己的邮箱或者不填

如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书-下一朵云
图3 安装acme.sh

默认情况下,acme.sh以隐藏文件夹的形式安装在用户的home目录下

另外,它还会创建一个定时任务,通过以下命令即可查看:

13 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

定时任务会在每天0点13分调用acme.sh程序,以检查证实是否过期,是否需要续签等。这个定时任务的时间是随机的,但不影响主要功能。

强烈建议添加一条别名命令方便后边执行

alias acme.sh=~/.acme.sh/acme.sh

3.运行acme.sh申请证书

完成安装后先来准备脚本,这个脚本只需要执行一次。执行后,这些信息会记录在相关目录中,后续的执行将自动执行

将之前步骤中准备好的阿里云Accesskey填写到上面命令的中,并在终端中执行,执行后并不会有内容返回

export Ali_Key="sddiwjedfasSDFSFsdaf"
export Ali_Secret="jlsdsddiwjedfasSDFSFkljlfdsaklkjflsa"

然后准备签发证书的命令,因为是签发,所以要使用“–issue”参数;指明使用“dns_ali”作为验证方式;后面跟着的“-d”为指定证书中的域名,这里有一点需要注意的:如果证书中只包含泛域名,那么签发出来的证书是没有根域的。所以需要额外添加一个根域

acme.sh --issue --dns dns_ali -d orcy.net -d *.orcy.net

在执行命令后,程序会调用阿里云的API,在DNS中添加以下内容:

如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书-下一朵云
图4 DNS记录

然后程序会等待120秒,以便让DNS生效,而后再调用Let’s Encrypt的API进行验证与证书的签发工作,如果一切正常,验证通过之后,会完成证书签发的工作,最后会将DNS中用于验证域名所有权的TXT解析记录删除。

如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书-下一朵云
图5 下发证书

其他厂商的DNS API信息请参考以下链接:https://github.com/Neilpang/acme.sh/tree/master/dnsapi

3.证书使用

完成签发后,再看看acme.sh安装目录中,会发现以相关域名命名的文件夹:

[root@centos .acme.sh]# ll -h
总用量 236K
-rw-r--r--. 1 root root  307 3月  14 20:02 account.conf
-rwxr-xr-x. 1 root root 205K 3月  14 18:15 acme.sh
-rw-r--r--. 1 root root   78 3月  14 18:15 acme.sh.csh
-rw-r--r--. 1 root root   78 3月  14 18:15 acme.sh.env
drwxr-xr-x. 3 root root   42 3月  14 19:51 ca
drwxr-xr-x. 2 root root 4.0K 3月  14 18:15 deploy
drwxr-xr-x. 2 root root 4.0K 3月  14 18:15 dnsapi
-rw-r--r--. 1 root root  518 3月  14 20:02 http.header
drwxr-xr-x. 2 root root  243 3月  14 18:15 notify
drwxr-xr-x. 2 root root  147 3月  14 20:02 orcy.net

域名文件夹中有以下文件:

[root@centos .acme.sh]# cd orcy.net/
[root@centos orcy.net]# ll -h
总用量 28K
-rw-r--r--. 1 root root 1.6K 3月  14 20:02 ca.cer
-rw-r--r--. 1 root root 3.4K 3月  14 20:02 fullchain.cer
-rw-r--r--. 1 root root 1.8K 3月  14 20:02 orcy.net.cer
-rw-r--r--. 1 root root  644 3月  14 20:02 orcy.net.conf
-rw-r--r--. 1 root root  976 3月  14 20:01 orcy.net.csr
-rw-r--r--. 1 root root  218 3月  14 20:01 orcy.net.csr.conf
-rw-r--r--. 1 root root 1.7K 3月  14 19:51 orcy.net.key

文件说明:

ca.cer:Let’s Encrypt的中级证书
fullchain.cer:包含中级证书的域名证书
orcy.net.cer:无中级证书的域名证书
orcy.net.conf:该域名的配置文件
orcy.net.csr:该域名的CSR证书请求文件
orcy.net.csr.conf:该域名的CSR请求文件的配置文件
orcy.net.key:该域名证书的私钥

相关命令:

openssl req -noout -text -in  orcy.net.csr    //检查csr文件
openssl rsa -noout -text -in  orcy.net.key    //检查私钥
openssl x509 -noout -text -in fullchain.cer   //检查证书文件

因为我主要将证书用在nginx,所以需要用到包含中级证书的域名证书与私钥,而其他文件请不要修改,同时请保护好acme.sh安装目录中的所有文件,一旦泄露请及时更换API key、吊销证书并且注销Let’s Encrypt账号。

具体配置如下

server {
  listen                     443 ssl;
  server_name                orcy.net;
 
  ssl_certificate            /usr/local/nginx/ssl/orcy.net.crt;
  ssl_certificate_key        /usr/local/nginx/ssl/orcy.net.key;
  ssl_buffer_size            16k;
  ssl_protocols              TLSv1.1 TLSv1.2 TLSv1.3;
  ssl_ecdh_curve             X25519:P-256:P-384:P-224:P-521;
  ssl_ciphers                TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
  ssl_prefer_server_ciphers  on;
  ssl_session_timeout        3h;
  ssl_stapling               on;
  ssl_session_tickets        on;
 
  access_log                 /var/log/nginx/access.log main;
 
  add_header                 Strict-Transport-Security "max-age=31536000; preload; includeSubDomains" always;
  add_header                 X-Frame-Options SAMEORIGIN;
 
  index                      index.php index.html;
 
  location / {
    root                     /usr/local/nginx/html;
  }
}

通过浏览器打开,即可检查证书的信息

如何使用acme.sh与阿里云DNS自动签发Let’s Encrypt的免费数字证书-下一朵云
图6 浏览器查看证书信息

Let’s Encrypt签发的证书有效期为90天,也就是说一年至少要更换4次。但是acme.sh支持自动部署,和调用脚本。这时候可以自行撰写脚本,将证书分发到各个节点。

**补充说明:copy/安装 证书**

前面证书生成以后, 接下来需要把证书 copy 到真正需要用它的地方

注意, 默认生成的证书都放在安装目录下: ~/.acme.sh/, 请不要直接使用此目录下的文件, 例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件. 这里面的文件都是内部使用, 而且目录结构可能会变化.

正确的使用方法是使用 --install-cert 命令,并指定目标位置, 然后证书文件会被copy到相应的位置, 例如:

Apache example:

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 example:

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"

(一个小提醒, 这里用的是 service nginx force-reload, 不是 service nginx reload, 据测试, reload 并不会重新加载证书, 所以用的 force-reload),测试中实测编译安装的nginx使用--reloadcmd "/usr/lcoal/nginx/sbin/nginx -s reolad"可以生效!

Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/.cer ,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。

--install-cert命令可以携带很多参数, 来指定目标文件. 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd会被自动调用,让服务器生效。

详细参数请参考: https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc

值得注意的是, 这里指定的所有参数都会被自动记录下来, 并在将来证书自动更新以后, 被再次自动调用。