最近在做一个 SASS 服务,为了防止用户上传违法信息导致域名被封,需要用户主动绑定自己的域名。绑定域名后,系统需要自动添加路由,自动申请 ssl 证书。
调研下来发现 apisix 这个开源的网关刚好支持通过调用 api 去动态添加路由和证书。对于申请 免费的 ssl 证书一般都是使用acme.sh
证书申请
acme 生成证书分为两种方式
-
DNS 验证
通过添加域名 TXT 记录验证,足以证明你对域名的控制权,所以也可以申请泛域名证书
-
文件验证
通过 http 访问域名验证,需要在指定路由下返回文本即可。这种方法无法证明你对域名的控制权,所以只能申请普通的单域名证书
上述过程可以通过acme.sh去一键完成
实现
-
调用 APISIX 接口添加文件验证路由绑定到域名
-
调用acme.sh
注意这里最好指定服务为
letsencrypt
,在国内调用会比较快这里是自己启动 http 验证,需要指定
-w
参数。生成的验证文件会放在${web_root}/.well-known/acme-challenge/
,需要写一个路由去去处理http://xxx/.well-known/*(.*)*
这个请求sh acme.sh --issue -m ${email} --server letsencrypt -d ${domain} -w ${web_root} sh acme.sh --install-cert -d ${domain} --key-file ${ssl_key} --fullchain-file ${ssl_cer}
-
调用 APISIX 接口删除文件验证路由
-
调用 APISIX 接口导入 SSL 证书
注意这里有个坑,导入证书接口文档没有说明需要传入证书的
start_time
和end_time
,但是Models里面又有,最好还是传下这两个参数,否则在 APISIX Dashboard 中查看证书会看不到过期时间时间。可以使用
openssl x509 -text -noout -in xxx.cer
命令解析出证书的 sni 和有效时间
因此可以写一个 RESTful 服务和 APISIX 部署在一个网络内,在服务启动时把自己的注册到 APISIX 中,然后实现以上功能即可
偷个懒
上述过程已经封装程一个 Docker 镜像 apisix-acme,直接使用即可