acme.sh 生成 ssl DV 证书的方法
acme.sh 项目地址:https://github.com/acmesh-official/acme.sh
1. 安装 acme.sh
https://github.com/acmesh-official/acme.sh/wiki/How-to-install
通过官方网站安装(此方式推荐国外的主机安装)
curl https://get.acme.sh | sh -s email=my@example.com
# 或
wget -O - https://get.acme.sh | sh -s email=my@example.com
通过 GitHub RAW 文件安装
curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m my@example.com
# 或
wget -O - https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m my@example.com
通过 Git 命令安装
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
高级安装
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install \
--home ~/myacme \
--config-home ~/myacme/data \
--cert-home ~/mycerts \
--accountemail "my@example.com" \
--accountkey ~/myaccount.key \
--accountconf ~/myaccount.conf \
--useragent "this is my client."
2. 配置 DNS
https://github.com/acmesh-official/acme.sh/wiki/dnsapi
将 DNS API 添加到 ~/.bashrc 内,并使之生效 source ~/.bashrc
export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje"
export CF_Account_ID="xxxxxxxxxxxxx"
3. 配置 DNS 别名模式(推荐)
别名模式好处:
- 可让不支持的 DNS 厂商通过现有已支持的厂商得到扩展支持;
- 可通过一个不重要的账号来统一生成证书,防止重要的 DNS Token 泄露;
https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode
首先设置域名别名(CNAME)
aliasDomainForValidationOnly.com 域名为 CloudFlare 上,的域名别名,example.com 域名为将要生成证书的域名。
将需要生成证书的域名 example.com 的主机名 _acme-challenge 设置为 _acme-challenge.aliasDomainForValidationOnly.com
_acme-challenge.example.com
=> _acme-challenge.aliasDomainForValidationOnly.com
即
_acme-challenge.example.com IN CNAME _acme-challenge.aliasDomainForValidationOnly.com.
签发证书
acme.sh --issue \
-d example.com --challenge-alias aliasDomainForValidationOnly.com --dns dns_cf
多个证书域名可以设置同一个别名
_acme-challenge.example.com
=> _acme-challenge.aliasDomainForValidationOnly.com
_acme-challenge.www.example.com
=> _acme-challenge.aliasDomainForValidationOnly.com
_acme-challenge.sub.example.com
=> _acme-challenge.aliasDomainForValidationOnly.com
_acme-challenge.example.net
=> _acme-challenge.aliasDomainForValidationOnly.com
_acme-challenge.example.org
=> _acme-challenge.aliasDomainForValidationOnly.com
支持泛域名
acme.sh --issue \
-d example.com --challenge-alias aliasDomainForValidationOnly.com --dns dns_cf \
-d example.net \
-d example.org \
-d *.example.com \
-d *.example.net \
-d *.example.org
多个域名分别不同的提供商
_acme-challenge.example.com
=> _acme-challenge.aliasDomainForValidationOnly.com
_acme-challenge.example.net
=> _acme-challenge.aliasDomainForValidationOnly2.com
签发证书
acme.sh --issue \
-d example.com --challenge-alias aliasDomainForValidationOnly.com --dns dns_cf \
-d example.net --challenge-alias aliasDomainForValidationOnly2.com
不同的 DNS 提供商
acme.sh --issue \
-d example.com --challenge-alias aliasDomainForValidationOnly.com --dns dns_cf \
-d example.net --challenge-alias aliasDomainForValidationOnly2.com --dns dns_gd
混合提供商
_acme-challenge.extern1.example.net
=> _acme-challenge.aliasDomainForValidationOnly.com
签发证书
./acme.sh/acme.sh --issue \
-d host1.example.com --challenge-alias no \
-d host2.example.com --challenge-alias no \
-d extern1.example.net --challenge-alias aliasDomainForValidationOnly.com \
--dns dns_infoblox
设置完成并签发证书后,不要移除相关的别名,否则会影响续签功能。
参数 challenge-alias or domain-alias 的不同
CNAME:
_acme-challenge.A.com
=> _acme-challenge.B.com
签发证书
acme.sh --issue -d a.com --challenge-alias b.com --dns dns_cf
若使用 --domain-alias,则别名 CNAME 应该设置为
CNAME:
_acme-challenge.A.com
=> myalias.B.com
签发证书
acme.sh --issue -d a.com --domain-alias myalias.B.com --dns dns_cf
案例
以 ZeroSSL 为例
注册账号
acme.sh --register-account -m myemail@example.com --server zerossl
或
acme.sh --register-account --server zerossl \
--eab-kid xxxxxxxxxxxx \
--eab-hmac-key xxxxxxxxx
签发证书
acme.sh --issue -d a.com --dns dns_cf --challenge-alias b.com -d *.a.com --keylength ec-256 --ecc --force
布署证书
acme.sh --install-cert --ecc -d a.com --key-file /usr/local/nginx/conf/ssl/a.com.key --fullchain-file /usr/local/nginx/conf/ssl/a.com.fullchain.cer --reloadcmd "systemctl reload nginx"
温馨提示:
若是想在本来就已签注的域名证书下,修改为别名模式,可通过修改对应域名的配置文件,再续签。
/acme.sh/a.com_ecc/a.com.conf
# 比如域名别名在 CloudFlare
Le_Webroot='dns_cf'
# 域名别名为 alias.com
Le_ChallengeAlias='alias.com,'
实例二
# 签发证书
acme.sh --issue -d aaa.com --dns dns_cf --challenge-alias xxx.xyz -d aaa.com -d *.bbb.com -d *...com --keylength ec-256 --ecc --force
# 部署证书
acme.sh --install-cert --ecc -d aaa.com --key-file /data/ssl/nginx/aaa.com.key --fullchain-file /data/ssl/nginx/aaa.com.fullchain.cer --reloadcmd "systemctl reload nginx"
- 使用 Stateless Mode(无状态模式)
无状态模式
将你的 Web 服务器配置为对给定账户密钥的验证请求进行无状态响应。这只需要一次性更改 Web 服务器配置,无需任何 “动态组件”。
首先获取你的账户密钥指纹:
root@ed:~# acme.sh --register-account
[Mon Feb 6 21:40:18 CST 2017] Registering account
[Mon Feb 6 21:40:19 CST 2017] Already registered
[Mon Feb 6 21:40:21 CST 2017] Update success.
[Mon Feb 6 21:40:21 CST 2017] ACCOUNT_THUMBPRINT='6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd'
记住最后一行的指纹:
6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd
配置 Web 服务器返回账户密钥指纹:
NGINX
在 nginx.conf 中添加类似内容:
http {
...
server {
...
location ~ ^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$ {
default_type text/plain;
return 200 "$1.6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd";
}
...
}
}
CADDY
在 Caddyfile 中添加类似内容:
example.com {
@achallenge {
path_regexp ch ^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$
}
respond @achallenge "{re.ch.1}.6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd"
APACHE
在 Apache 2.4.62 上测试通过
在 httpd.conf 中添加类似内容:
...
<VirtualHost *:80>
...
<LocationMatch "/.well-known/acme-challenge/(?<challenge>[-_a-zA-Z0-9]+)">
RewriteEngine On
RewriteRule "^([-_a-zA-Z0-9]+)$" "$1" [E=challenge:$1]
ErrorDocument 200 "%{ENV:MATCH_CHALLENGE}.6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd"
RewriteRule ^ - [L,R=200]
</LocationMatch>
...
</VirtualHost>
...
HAPROXY
在你的配置中添加 http-request return 规则:
global
setenv ACCOUNT_THUMBPRINT '6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd'
log stderr local0
stats socket /var/run/haproxy.sock level admin mode 0666
frontend web
log global
option httplog
mode http
bind :80
bind :443 ssl crt /etc/haproxy/certs/
http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].${ACCOUNT_THUMBPRINT}\n" if { path_reg '^/.well-known/acme-challenge/[-_a-zA-Z0-9]+$' }
好了,现在你可以颁发证书了。
acme.sh --issue -d example.com --stateless
https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode