let's-encrypt

2018 年 3 月 14 日,Let’s Encrypt 对外宣布 ACME v2 已正式支持泛域名证书。这就意外味着用户可以在 Let’s Encrypt 上免费申请支持泛域名的 SSL 证书。

什么是 Let’s Encrypt

部署 HTTPS 网站的时候需要证书,证书由 CA 机构签发,大部分传统 CA 机构签发证书是需要收费的,这不利于推动 HTTPS 协议的使用。

Let’s Encrypt 也是一个 CA 机构,但这个 CA 机构是免费的! 也就是说签发证书不需要任何费用。

Let’s Encrypt 是国外一个公共的免费 SSL 项目,由 Linux 基金会托管。由 Mozilla、思科、Akamai、IdenTrust 和 EFF 等组织发起,目的就是向网站自动签发和管理免费证书。以便加速互联网由 HTTP 过渡到 HTTPS,目前 Facebook 等大公司开始加入赞助行列。

Let’s Encrypt 已经得了 IdenTrust 的交叉签名,这意味着其证书现在已经可以被 Mozilla、Google、Microsoft 和 Apple 等主流的浏览器所信任。用户只需要在 Web 服务器证书链中配置交叉签名,浏览器客户端会自动处理好其它的一切,Let’s Encrypt 安装简单,使用非常方便。

什么是泛域名证书

泛域名证书类似 DNS 解析的泛域名概念,泛域名证书就是证书中可以包含一个通配符。主域名签发的泛域名证书可以在所有子域名中使用,比如 demo.domain.com、bbs.domain.com。这样就一张证书可以用于更多的主机了

如何申请 Let’s Encrypt 泛域名证书

Let’s Encrypt 上的证书申请是通过 ACME 协议来完成的。ACME 协议规范化了证书申请、更新、撤销等流程,实现了 Let’s Encrypt CA 自动化操作。解决了传统的 CA 机构是人工手动处理证书申请、证书更新、证书撤销的效率和成本问题。

ACME v2 是 ACME 协议的更新版本,泛域名证书只能通过 ACME v2 获得。要使用 ACME v2 协议申请泛域名证书,只需一个支持该协议的客户端就可以了,官方推荐的客户端是 Certbot。

安装Certbot

如果没有下载安装过Certbot,先下载Certbot客户端

1
2

wget https://dl.eff.org/certbot-auto

然后把certbot-auto设为可执行权限

1
2

chmod a+x certbot-auto

升级Certbot

如果已经安装了Certbot,查看下自己的Certbot客户端是不是支持 ACME v2 版本,官方介绍 Certbot 0.22.0 版本支持新的协议版本

1
2
3
4
5
6
7

./certbot-auto --version
Upgrading certbot-auto 0.21.1 to 0.25.1...
Replacing certbot-auto...

./certbot-auto --version
certbot 0.22.0

客户在申请 Let’s Encrypt 证书的时候,需要校验域名的所有权,证明操作者有权利为该域名申请证书,目前支持三种验证方式:

  1. dns-01:给域名添加一个 DNS TXT 记录。
  2. http-01:在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。
  3. tls-sni-01:在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。

申请泛域名证书

申请泛域名证书,只能使用 dns-01 的方式

使用 Certbot 客户端申请证书方法比较的简单,输入以下命令:

1
2

./certbot-auto certonly -d domain.com -d *.domain.com --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

1、把domain换成你自己的域名。

2、*.domain.com可作用于所有子域名,但好像不能作用于domain.com,所以加上domain.com这样的裸域名。

相关参数说明

  1. certonly,表示安装模式,Certbot 有安装模式和验证模式两种类型的插件。
  2. --manual 表示手动安装插件,Certbot 有很多插件,不同的插件都可以申请证书,用户可以根据需要自行选择
  3. -d 为那些主机申请证书,如果是通配符,输入 *.domain.com(可以替换为你自己的域名)
  4. --preferred-challenges dns,使用 DNS 方式校验域名所有权
  5. --server,Let’s Encrypt ACME v2 版本使用的服务器不同于 v1 版本,需要显示指定。

执行完这一步之后,就是命令行的输出,请根据提示输入相应内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
dns-01 challenge for xxxxx.com
dns-01 challenge for xxxxx.com

-------------------------------------------------------------------------------
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
-------------------------------------------------------------------------------
(Y)es/(N)o: y

上述有两个交互式的提示:

  1. 是否同意 Let’s Encrypt 协议要求
  2. 询问是否对域名和机器(IP)进行绑定

确认同意才能继续。

继续查看命令行的输出,非常关键:

1
2
3
4
5
6
7
8
9
10

-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.xxxxx.com with the following value:

XQOqY8npyso******ovtudA3zMd_C1dh9bjMEkbkKHM

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue

执行到上图最后一步时,先暂时不要回车。要求配置 DNS TXT 记录,从而校验域名所有权,也就是判断证书申请者是否有域名的所有权。接下来需要按照提示在域名后台添加对应的 DNS TXT 记录。

上面输出要求给 _acme-challenge. XXXXX.com 配置一条 TXT 记录,在没有确认 TXT 记录生效之前不要回车执行。

我使用的是阿里云的域名服务器,登录控制台操作如下图:

泛域名证书

如上图所示,有两条DNS TXT,因为我们申请的时候就有两个域名,domain.com 和 *.domain.com,所以我们在阿里云的后台添加一条DNS TXT后,我们回到命令行,按回车继续,然后会输出第二条DNS TXT

1
2
3
4
5
6
7
8
9
10

-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.xxxxx.com with the following value:

XQOqY8npyso******ovtudA3zMd_C1dh9bjMEkbkKHM

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue

同样,按照上面的步骤在阿里云的后台多加一条DNS TXT解析就好。加完稍等几分钟后,回到命令行,按回车

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/dengtongyu.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/dengtongyu.com/privkey.pem
Your cert will expire on 2018-XX-XX. To obtain a new or tweaked
version of this certificate in the future, simply run certbot-auto
again. To non-interactively renew *all* of your certificates, run
"certbot-auto renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Press Enter to Continue

看到上面的输出,说明已经生效。

你也可以输入以下命令确认 TXT 记录是否生效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

dig -t txt _acme-challenge.XXXXXX.com @8.8.8.8

; <<>> DiG 9.10.6 <<>> -t txt _acme-challenge.XXXXXX.com @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55138
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;_acme-challenge.XXXXXX.com.INTXT

;; ANSWER SECTION:
_acme-challenge.XXXXXX.com.599 INTXT"bQzqaEADZbE******KvPiltbucW130jaj9PNTkAH3mU"
_acme-challenge.dengtongyu.com.599 INTXT"XQOqY8npyso******ovtudA3zMd_C1dh9bjMEkbkKHM"

;; Query time: 175 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Jul 12 10:59:20 CST 2018
;; MSG SIZE rcvd: 171

到了这一步后,恭喜您,证书申请成功。 证书和密钥保存在下列目录:

1
2
3
4
5
6
7

/etc/letsencrypt/live/xxx.com/

├── cert.pem
├── chain.pem
├── fullchain.pem
└── privkey.pem

然后校验证书信息,输入如下命令:

1
2
3
4
5
6
7
8
9
10

openssl x509 -in /etc/letsencrypt/live/xxx.com/cert.pem -noout -text
...
Authority Information Access:
OCSP - URI:http://ocsp.int-x3.letsencrypt.org
CA Issuers - URI:http://cert.int-x3.letsencrypt.org/

X509v3 Subject Alternative Name:
DNS:*.xxx.com
...

可以看到证书包含了 SAN 扩展,该扩展的值就是 *.xxx.com

在 Nginx 中 配置 Let’s Encrypt 证书

Nginx 配置文件片断:

1
2
3
4
5
6
7
8
9
10
11
12

server {
server_name xxx.com;
listen 443 http2 ssl;
ssl on;
ssl_certificate /etc/letsencrypt/live/XXXXXX.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/XXXXXX.com/privkey.pem;

location / {
proxy_pass http://127.0.0.1:8080;
}
}