0x01 前言
Let’s Encrypt项目开展一年多了,很早以前已经支持泛域名证书的签发,而我的博客从该项目正式运行的时候也切换到Let’s Encrypt的数字证书。
刚开始的时候签发证书比较繁琐,需要自己手敲命令,但后来有位大佬创建了acme.sh这个项目,以下是该项目的GitHub地址:
通过访问acme.sh一样可以打开该项目的GitHub页面噢。因为该项目是国人创建的,所以会有中文版本的说明文档。
而今天这篇文章只是记录下我日常使用的情况,主要结合阿里云的DNS服务申请和续签免费的Let’s Encrypt数字证书。因为我使用的功能比较单一,所以文章里没有其他高级功能的部分,如果有需要,请留意该项目的中文说明部分。如果以后有需求,我会撰写文章,额外说明。
0x02 准备
Let’s Encrypt只支持DV证书的签发,也就是通过验证域名所有权,然后签发该域名的证书。它支持两种验证方式,一种是通过HTTP的方式验证,另一种是通过DNS的方式验证,而今天要讲的就是第二种方式。
首先得准备一个可以使用阿里云DNS解析服务的阿里云账号。阿里云的DNS解析服务是免费的,但免费版本的TTL最小为10分钟,如果需要更小的TTL值,则需要购买升级服务。相关咨询可以参考以下文章:
但Let’s Encrypt验证DNS对TTL并没有要求,用免费版的阿里云DNS解析服务是可以的。
紧接着需要将你的域名解析权赋予阿里云,首先在阿里云的DNS解析服务中添加你的域名:
域名添加完成后会给出两个DNS服务器的域名,这时候需要在你购买域名的厂商中将域名的DNS服务器修改为给出的DNS服务器即可。
稍等片刻,当页面中出现绿色勾勾,则说明DNS服务器切换完成,你域名正由阿里云提供解析服务。
接下来要准备acme.sh源码,直接使用git clone即可将源码克隆到本地:
[root@b695a3 ~]# git clone https://github.com/Neilpang/acme.sh.git
在签发证书前还得准备阿里云账户的API key,打开以下地址并创建AccessKey即可:
注意!阿里云支持子账户功能,为了提高安全性,请参考阿里云的文档,创建子账户后再创建API key,但这不是必须操作的。
创建完成后将AccessKey ID与Access Key Secret记下来备用。
0x03 acme.sh
我们已经准备好一切,接下来先安装acme.sh到本地,进入源码文件夹并执行以下命令即可:
# 进入文件夹 [root@b695a3 ~]# cd acme.sh/ # 安装 [root@b695a3 acme.sh]# ./acme.sh --install [Sun Jan 27 19:23:03 HKT 2019] It is recommended to install socat first. [Sun Jan 27 19:23:03 HKT 2019] We use socat for standalone server if you use standalone mode. [Sun Jan 27 19:23:03 HKT 2019] If you don't use standalone mode, just ignore this warning. [Sun Jan 27 19:23:03 HKT 2019] Installing to /root/.acme.sh [Sun Jan 27 19:23:03 HKT 2019] Installed to /root/.acme.sh/acme.sh [Sun Jan 27 19:23:03 HKT 2019] Installing alias to '/root/.bashrc' [Sun Jan 27 19:23:03 HKT 2019] OK, Close and reopen your terminal to start using acme.sh [Sun Jan 27 19:23:03 HKT 2019] Installing alias to '/root/.cshrc' [Sun Jan 27 19:23:03 HKT 2019] Installing alias to '/root/.tcshrc' [Sun Jan 27 19:23:03 HKT 2019] Installing cron job no crontab for root no crontab for root [Sun Jan 27 19:23:03 HKT 2019] Good, bash is found, so change the shebang to use bash as preferred. [Sun Jan 27 19:23:03 HKT 2019] OK
默认情况下,acme.sh以隐藏文件夹的形式安装在用户的home目录下,而我是用root用户,所以它在这里:
[root@b695a3 acme.sh]# ll /root/.acme.sh/ total 188 -rw-r--r-- 1 root root 96 Jan 27 19:23 account.conf -rwxr-xr-x 1 root root 169557 Jan 27 19:23 acme.sh -rw-r--r-- 1 root root 78 Jan 27 19:23 acme.sh.csh -rw-r--r-- 1 root root 78 Jan 27 19:23 acme.sh.env drwxr-xr-x 2 root root 4096 Jan 27 19:23 deploy drwxr-xr-x 2 root root 4096 Jan 27 19:23 dnsapi
另外,它还会创建一个定时任务,通过以下命令即可查看:
[root@b695a3 acme.sh]# crontab -e 3 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
定时任务会在每天0点3分调用acme.sh程序,以检查证实是否过期,是否需要续签等。这个定时任务的时间是随机的,但不影响主要功能。
完成安装后先来准备脚本,这个脚本只需要执行一次。执行后,这些信息会记录在相关目录中,后续的执行将自动执行:
# 首先执行以下两行 export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" export Ali_Secret="jlsdflanljkljlfdsaklkjflsa" # 而后申请签发证书 acme.sh --issue --dns dns_ali -d m4d3bug.com -d *.m4d3bug.com
将之前步骤中准备好的阿里云API key填写到上面命令的中,并在终端中执行,执行后并不会有内容返还:
然后准备签发证书的命令,因为是签发,所以要使用“–issue”参数;指明使用“dns_ali”作为验证方式;后面跟着的“-d”为指定证书中的域名,这里有一点需要注意的:如果证书中只包含泛域名,那么签发出来的证书是没有根域的。所以需要额外添加一个根域,如上面的命令所示。
其他厂商的DNS API信息请参考以下链接:
完成后即可到acme.sh的安装目录中执行:
# 进入文件夹 [root@b695a3 ~]# cd /root/.acme.sh/ # 执行命令 [root@b695a3 .acme.sh]# ./acme.sh --issue --dns dns_ali -d m4d3bug.com -d *.m4d3bug.com [Sun Jan 27 19:39:36 HKT 2019] Registering account [Sun Jan 27 19:39:37 HKT 2019] Registered [Sun Jan 27 19:39:37 HKT 2019] ACCOUNT_THUMBPRINT='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' [Sun Jan 27 19:39:37 HKT 2019] Creating domain key [Sun Jan 27 19:39:37 HKT 2019] The domain key is here: /root/.acme.sh/m4d3bug.com/m4d3bug.com.key [Sun Jan 27 19:39:37 HKT 2019] Multi domain='DNS:m4d3bug.com,DNS:*.m4d3bug.com' [Sun Jan 27 19:39:37 HKT 2019] Getting domain auth token for each domain [Sun Jan 27 19:39:40 HKT 2019] Getting webroot for domain='m4d3bug.com' [Sun Jan 27 19:39:40 HKT 2019] Getting webroot for domain='*.m4d3bug.com' [Sun Jan 27 19:39:40 HKT 2019] Found domain api file: /root/.acme.sh/dnsapi/dns_ali.sh [Sun Jan 27 19:39:42 HKT 2019] Found domain api file: /root/.acme.sh/dnsapi/dns_ali.sh [Sun Jan 27 19:39:45 HKT 2019] Sleep 120 seconds for the txt records to take effect
在执行命令后,程序会调用阿里云的API,在DNS中添加以下内容:
然后程序会等待120秒,以便让DNS生效,而后再调用Let’s Encrypt的API进行验证与证书的签发工作:
如果一切正常,验证通过之后,会完成证书签发的工作,最后会将DNS中用于验证域名所有权的TXT解析记录删除:
0x04 使用
完成签发后,再看看acme.sh安装目录中,会发现以相关域名命名的文件夹:
[root@b695a3 .acme.sh]# ll /root/.acme.sh/ total 192 -rw-r--r-- 1 root root 251 Jan 27 19:42 account.conf -rwxr-xr-x 1 root root 169557 Jan 27 19:23 acme.sh -rw-r--r-- 1 root root 78 Jan 27 19:23 acme.sh.csh -rw-r--r-- 1 root root 78 Jan 27 19:23 acme.sh.env drwxr-xr-x 3 root root 42 Jan 27 19:39 ca drwxr-xr-x 2 root root 4096 Jan 27 19:23 deploy drwxr-xr-x 2 root root 4096 Jan 27 19:23 dnsapi -rw-r--r-- 1 root root 395 Jan 27 19:42 http.header drwxr-xr-x 2 root root 162 Jan 27 19:42 m4d3bug.com
域名文件夹中有以下文件:
[root@b695a3 .acme.sh]# ll /root/.acme.sh/m4d3bug.com/ total 28 -rw-r--r-- 1 root root 1648 Jan 27 19:42 ca.cer -rw-r--r-- 1 root root 3567 Jan 27 19:42 fullchain.cer -rw-r--r-- 1 root root 1919 Jan 27 19:42 m4d3bug.com.cer -rw-r--r-- 1 root root 536 Jan 27 19:42 m4d3bug.com.conf -rw-r--r-- 1 root root 989 Jan 27 19:39 m4d3bug.com.csr -rw-r--r-- 1 root root 224 Jan 27 19:39 m4d3bug.com.csr.conf -rw-r--r-- 1 root root 1675 Jan 27 19:39 m4d3bug.com.key
相关文件的用途如下:
- ca.cer:Let’s Encrypt的中级证书
- fullchain.cer:包含中级证书的域名证书
- m4d3bug.com.cer:无中级证书的域名证书
- m4d3bug.com.conf:该域名的配置文件
- m4d3bug.com.csr:该域名的CSR证书请求文件
- m4d3bug.com.csr.conf:该域名的CSR请求文件的配置文件
- m4d3bug.com.key:该域名证书的私钥
因为我主要将证书用在nginx,所以需要用到包含中级证书的域名证书与私钥,而其他文件请不要修改,同时请保护好acme.sh安装目录中的所有文件,一旦泄露请及时更换API key、吊销证书并且注销Let’s Encrypt账号。
接下来通过nginx进行测试,以下是配置文件:
server { listen 443 ssl http2; server_name m4d3bug.com; ssl_certificate /usr/local/nginx/ssl/m4d3bug.com.crt; ssl_certificate_key /usr/local/nginx/ssl/m4d3bug.com.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; } }
通过浏览器打开,即可检查证书的信息:
0x05 结语
Let’s Encrypt签发的证书有效期为90天,也就是说一年至少要更换4次。这是完全不可接受的,要是忘记不就完蛋了?
还好acme.sh支持自动部署,和调用脚本。这时候可以自行撰写脚本,将证书分发到各个节点,这个有时间再写文章了。