使用ACME v2 API签发Let's Encrypt野卡SSL证书

去年年底,Let's Encrypt发布了其2018年的计划。其中,在“新功能”一节里提到在今年2月27日,ACME protocol API将会升级到v2版本,升级后用户将能够签发Wildcard证书,也就是所谓的“野卡”,不了解这是什么的话可以去看看wiki。能免费用上野卡,想想就很激动,然而几个月过去,我都快忘了这事的时候,今天Telegram群里突然有人说Let's Encrypt能签发野卡了。我赶紧跑去一看,发现官方在社区里发布了帖子,宣布ACME v2 API正式上线了。现在回去看去年的计划,发现实际上是跳票了。于是我今天就给自己手里的一个域名签了一张野卡证书,签发过程不麻烦,只要你用对了工具。

支持ACME v2 API的客户端

这次升级是个不小的升级,而野卡也只能使用v2版本的API签发,今天官方发的帖子里也说了,你需要一个支持ACME v2的客户端,官方有一个列表可供参考。

之前我使用的客户端一直是原Let's Encrypt官方客户端letsencrypt-auto,现由EFF维护的客户端Certbot。此客户端使用Python编写,之前在用的过程中虽然也没出过什么大问题,但说实话用起来总感觉不顺手。具体体现在以下几点:

  1. 依赖Python(虽然这个基本上是现在发行版的标配,但是有些精简的发行版,比如OpenWRT,就没有默认安装有Python)
  2. 使用Python virtualenv运行,每次运行时都要先等半天才能开始
  3. 会产生很多垃圾在/root/和其配置存储目录下
  4. 半自动,很多事比如配置定时自动更新证书都要用户自己做

当然,又不是不能用,crontab又不是不会写,但是今天我一运行傻了,提示不支持签发野卡,说好的已经上线了呢?我感觉是客户端版本太低了,但是我明明刚apt upgrade过啊?于是我检查了一下版本,0.19.0,而官方的列表显示至少要0.22.0才支持ACME v2,然而软件包又没更新?那可能是发行版太旧了吧,然后我换了台Ubuntu 17.10的机器,更新软件包,一看certbot版本,0.21.0

这算什么鬼,我于是决定抛弃这个辣鸡,换其他的客户端看看。看了一下列表,有3个客户端是纯bash脚本实现的,说是也不需要其他依赖,我试了一下以后选择了个人感觉最好用的acme.sh

使用 acme.sh 签发野卡证书

1. 安装

首先,安装 acme.sh。方法很简单,一行命令解决:

curl https://get.acme.sh | sh

或者

wget -O - https://get.acme.sh | sh

这会将acme.sh安装到你的$HOME目录下。当然,你也可以根据文档进行自定义安装。

比如你可以指定安装位置到\etc\acme.sh

git clone https://github.com/Neilpang/acme.sh.git
cd acme.sh
./acme.sh --install --home /etc/acme.sh

安装后acme.sh的脚本实际上保存在$install_dir/acme.sh,比如我的就在/etc/acme.sh/acme.sh。安装时会自动向你的~/.bashrc添加alias,所以在安装完以后你需要退出bash重新进入,或者运行source .profile使alias生效。

但是我日常用的shell是fish,而acme.sh并没有对fish做特殊配置,这时候就需要手动配置一下,不然运行的时候还要输入完整的路径。

tail -n 1 ~/.bashrc >> ~/.config/fish/config.fish

然后同样是重新进入fish,就能直接使用acme.sh命令了。

2. 签发证书

签发野卡需要使用DNS模式,这需要你先去自己的DNS服务商获取API key和secret。

acme.sh已经支持的DNS提供商可以在这个列表里找到,如果你的提供商不在这个列表里面,你可以提交issue请求添加(但请注意作者没有义务为你添加),也可以更换到支持的服务商,或者你可以试试手动添加DNS记录。这里以我使用的GoDaddy为例:

首先去GoDaddy的开发者平台获取API key和secret。注意,如果是第一次添加key,打开页面后会只能先添加一个Test Key,而我们需要的是Production Key(辣鸡GoDaddy)。所以先添加一个Test Key,然后添加完我们需要的Production Key,记录好key和secret(关闭后不能再查看secret),最后再删除一开始添加的Test Key即可。

然后运行如下命令(如果你使用其他服务商,参数名会不一样,具体请参考上面提到的提供商列表):

export GD_Key="你的key"
export GD_Secret="你的secret"

然后就可以用DNS模式签发证书了,运行:

acme.sh --issue --dns dns_gd -d yourdomain.com -d *.yourdomain.com

不过为了更高的安全系数,我们可以在上面的命令后面加入-k参数,签发一个ECC证书:

acme.sh --issue --dns dns_gd -d yourdomain.com -d *.yourdomain.com -k ec-384

这里-k的参数可以是ec-256(ECDSA P-256),ec-384(ECDSA P-384)或者ec-521(ECDSA P-521)(目前Let's Encrypt暂不支持P-521)

注意这里除了给子域名使用通配符,对于根域名也需要单独添加。因为所谓的通配符,只会匹配当前这一级子域名,所以不论是*.subdomain.yourdomain.com这种二级子域名还是yourdomain.com这个根域名都是没有匹配的,所以说野卡其实也没什么大不了。毕竟真正牛逼的是EV证书

你可能会担心上面export的key和secret关了shell就消失了,其实不用担心,因为acme.sh已经自动帮你保存到了$install_dir/account.conf里了,以后会自动使用这里面保存的参数。

等待大约2分30秒左右(等待DNS记录生效需要2分钟,其他模式会很快),签发好的证书就会被存放在acme.sh的安装目录下了,其路径也会在脚本运行的最后打印出来。

然后就可以修改nginx或Apache的配置,使用签发的野卡了,至于更新证书之类的事就完全不用管了,acme.sh已经帮你做好一切。由于使用了DNS模式,所以也不需要考虑先关闭nginx防止80端口被占用无法使用standalone模式验证的问题。

修改好nginx配置,重启nginx,打开浏览器,可以看到证书已经是刚才签发的野卡了,而且也是更安全的ECC证书了。

标签: SSL, 证书, Let's Encrypt, acme.sh

添加新评论