前段时间因需求在阿里云上搭建过一次基于let's encrypt的nginx免费通配符证书,当时因为有阿里云的API接口,搭建的比较顺利,最近由于公司内部测试需要,测试机没有类似阿里云之类的API接口,在搭建的时候发现http-01的方式没法配置通配符证书,最后在github上找到了一种方法,所以现在就把两种方式都回顾下。

acme原理:https://blog.csdn.net/canghaiguzhou/article/details/79945001

ACME 协议支持的验证协议一般有两种:

http 验证:必须有可以正常运行的服务器和公网 IP。验证时,需要在你的网站根目录下放一个文件来验证域名所有权,完成验证后就可以生成证书了。 dns 验证:不需要服务器和公网 IP。只需要为域名添加一条 txt 解析记录来验证域名所有权。

通过 acme.sh 获取通配符域名证书

acme.sh 的所有相关文件(包括安装文件、申请到的证书等)都在 ~/.acme.sh/ 这一个目录中。

安装 acme.sh 在线安装 curl https://get.acme.sh | sh 或者: wget -O - https://get.acme.sh | sh

从 Git 安装 git clone https://github.com/Neilpang/acme.sh.git cd ./acme.sh ./acme.sh --install

安装过程包含 3 个动作:

创建并复制 acme.sh 到你的家目录 $HOME:~/.acme.sh/。所有的证书都会放到这个目录中 创建别名: acme.sh=~/.acme.sh/acme.sh 创建每天的定时任务检查证书,如果快要到期了会自动更新 定时任务示例:

0 "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null

验证 安装完成后,需要重新打开终端,acme.sh 命令才能生效

第一种DNS方式: 如果域名解析商提供 API,则可以自动借助这个 API 通过工具添加 txt 记录完成验证。

例如阿里云: 首先我们要把acme的配置替换成从阿里云获取的API参数 vim .acme.sh/account.conf

SAVEDAliKey='XXXXXX' SAVEDAliSecret='XXXXXX'

修改完配置后,执行命令: acme.sh --issue --dns dns_ali -d mydomain.com -d .mydomain.com

acme.sh 会保存 API 参数并生成定时任务,用于每天验证证书是否即将过期,并及时更新。下面是通过 crontab -e 看到的新增的定时任务: 16 0 "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

证书生成后,需要把证书 copy 到真正需要用它的地方。

默认生成的证书都放在安装目录 ~/.acme.sh/ 下,但是请不要直接使用。而是使用 --installcert 命令安装证书。

使用 --installcert 命令安装证书

使用 --installcert 命令安装证书时,证书文件会被复制到相应的位置:

acme.sh --installcert -d mydomain.com
--key-file /etc/nginx/ssl/mydomain.key
--fullchain-file /etc/nginx/ssl/fullchain.cer
--reloadcmd "systemctl reload nginx.service"

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

server{ listen 443 ssl; server_name mydomain.com; ssl on; ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/mydomain.key; ssl_session_timeout 5m; }

第二种http方式: 这种方式如果只是单独一个或者多个域名,直接执行命令即可,后边呢的webroot是存放证书的目录,可以手动修改增加

acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/

如果没有运行任何 web 服务,80 端口是空闲的,那么 acme.sh 可以运行为 webserver,临时监听 80 端口,完成验证:

acme.sh --issue -d mydomain.com --standalone

这里我在申请证书的时候遇到过一个问题,域名的公网IP+80其实是映射到我内网的IP+8080端口,但是我误认为是内网的80端口,所以在nginx的配置中我监听了80端口,导致验证文件一直下载不下来,最后修改了nginx监听8080端口后解决。 报错信息: http://mydomain/.well-known/acme-challenge/YdvMFXcNTtNkZGWop-ZOXYSFR5qNlTn8AQvGhGg9Yww not found

问题解决后,发现申请下来的证书无法支持通配符,最终在github上找到了通过域名别名的解决方式。

http方式 支持https通配符免费证书:

首先,我们需要在DNS服务器上设置我们的域名别名: _acme-challenge.mydomain.cn CNAME到 _acme-challenge.alidomain.cn

这里我们做的操作是把要申请证书的域名CNAME到原先可以通过API接口申请通配符的域名上,前边的_acme-challenge是必须要加的 而且我也还要配置.acme.sh/account.conf下 原先域名的key,完成后执行操作。

acme.sh --issue -d mydomain.cn --challenge-alias alidomain.cn --dns dns_ali -d *.mo-sky.cn 如果提示 可以加上 --force 参数

参考文章:https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode