什么是 Let's Encrypt

Let's Encrypt 是免费、开放和自动化的证书颁发机构。由非盈利组织互联网安全研究小组(ISRG)运营。Let's Encrypt 提供的是域名验证型(DV)证书,有效期为 90 天,证书快到期时可以通过脚本自动续期。中文官网是 https://letsencrypt.org/zh-cn/

以往我们申请 SSL 证书,通常是在 IDC 服务商的管理后台页面填写表单进行申请,而 Let's Encrypt 则是通过命令行提交申请,操作也很简单。Let's Encrypt 使用 ACME 协议来验证您对给定域名的控制权并向您颁发证书,最常用的是就是 ACME 客户端软件是  Certbot

什么是通配符证书

在申请通配符证书前,我们首先要了解什么是通配符域名。

举例 *.yangdx.com 这个通配符域名,可以匹配 www.yangdx.comblog.yangdx.comimg.yangdx.com 等二级域名,我们为 *.yangdx.com 申请通配符证书,就可以保护所有的二级域名。

根域名 yangdx.com 比较特殊,如果要把它包含到 *.yangdx.com 的证书里,需要手动指定。

下面,我们开始申请通配符证书。

申请通配符证书

首先,安装 Certbot 客户端(要用 root 账户操作):

$ wget https://dl.eff.org/certbot-auto
$ mv certbot-auto /usr/local/bin/certbot-auto
$ chmod 0755 /usr/local/bin/certbot-auto

接着,执行 certbot-auto 申请证书,指令如下:

$ certbot-auto certonly \
  -d "*.yangdx.com" \
  -d "yangdx.com" \
  --manual \
  --preferred-challenges dns-01 \
  --server https://acme-v02.api.letsencrypt.org/directory

参数说明:

  • certonly 表示安装模式,Certbot 有安装模式和验证模式两种类型的插件。
  • -d 域名 要使用此证书的域名,可以多个,但通配符域名最多一个。
  • --manual 表示手动安装插件,Certbot 有很多插件,不同的插件都可以申请证书,用户可以根据需要自行选择。
  • --preferred-challenges 验证方式 验证域名所有权的方式,目前有以下三种:
    • dns-01 - 给域名添加一个 DNS TXT 记录。对于通配符域名,只能使用 dns-01 方式验证;
    • http-01 - 在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件;
    • tls-sni-01 - 在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。
  • --server 认证中心URL 认证中心的 URL,对于通配符域名,目前只有 Let's Encrypt ACME v2 版本的认证中心支持通配符证书。

首次执行 certbot-auto ,它会判断 Linux 系统内核版本,并自动安装一些依赖包,请确认并耐心等待。依赖包安装完后,开始进入申请证书步骤。下面是安装记录,我穿插了中文释义。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): admin@yangdx.com  <-- 输入email地址用于接收证书续期提醒和安全通知

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A  <-- 是否同意服务条款

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y  <-- 是否接收来自EFF的新闻、活动等邮件通知
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for yangdx.com
dns-01 challenge for yangdx.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  <-- 是否允许记录本机IP

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.yangdx.com with the following value:  <-- 请为此域名添加TXT记录值

q0NM5SpBkkcjsL0ged3W8R7WZO3R0kqNQqg6UoIS9rY  <-- TXT记录值(这是第1条)

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue  <-- 添加TXT记录后按Enter键进行验证

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.yangdx.com with the following value:  <-- 请为此域名添加TXT记录值

TURj1X2c1I5TuDginBgCDCv-wlyWaZplPQQSLqnqleg  <-- TXT记录值(这是第2条)

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue  <-- 添加TXT记录后,请过几分钟再按Enter键进行验证
Waiting for verification...
Cleaning up challenges
Subscribe to the EFF mailing list (email: yang@yangdx.com).

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/yangdx.com/fullchain.pem  <-- 这是证书的保存路径
   Your key file has been saved at:
   /etc/letsencrypt/live/yangdx.com/privkey.pem  <-- 这是证书的私钥路径
   Your cert will expire on 2020-11-20. To obtain a new or tweaked  <-- 过期时间2020-11-20
   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

添加 DNS TXT 记录的操作,这里就不再阐述,因为每个域名服务商的 DNS 解析操作基本相同。

需要注意的是,因为我们同时为 *.yangdx.comyangdx.com 申请证书,所以需要做两次 TXT 记录验证(相同的 _acme-challenge.yangdx.com 是可以添加多条 TXT 记录的)。添加 TXT 记录后,不要马上按 Enter 键进行验证,DNS 解析生效需要一点时间。

账号凭据、证书文件,都保存在 /etc/letsencrypt 目录,请注意备份。

查看证书

使用 certbot-auto certificates 指令可查看当前申请的证书和它的过期时间:

$ certbot-auto certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: yangdx.com
    Serial Number: 3722e458be3138949f48c9aefd06604***d
    Domains: *.yangdx.com yangdx.com
    Expiry Date: 2020-11-20 12:48:43+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/yangdx.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/yangdx.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

证书续期

证书有效期为 90 天,即将过期时,我们可以执行 certbot-auto renew 进行自动续期。

如果你的服务器是在大陆,执行 certbot-auto renew 指令可能会遇到下面这个错误:

OCSP check failed for /etc/letsencrypt/archive/yangdx.com/cert1.pem (are we offline?)
Traceback (most recent call last):
  File "/opt/eff.org/certbot/venv/lib/python2.7/site-packages/certbot/ocsp.py", line 188, in _check_ocsp_cryptography
    timeout=timeout)
  File "/opt/eff.org/certbot/venv/lib/python2.7/site-packages/requests/api.py", line 119, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/opt/eff.org/certbot/venv/lib/python2.7/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/opt/eff.org/certbot/venv/lib/python2.7/site-packages/requests/sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "/opt/eff.org/certbot/venv/lib/python2.7/site-packages/requests/sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "/opt/eff.org/certbot/venv/lib/python2.7/site-packages/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
ConnectionError: HTTPConnectionPool(host='ocsp.int-x3.letsencrypt.org', port=80): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f5702227b90>: Failed to establish a new connection: [Errno 110] Connection timed out',))

程序需要访问 http://ocsp.int-x3.letsencrypt.org (URL中的数字可能是1~4)进行 OCSP 验证,该域名在大陆可能无法解析,需要手动指定 host。打开 https://www.ipaddress.com ,查询 ocsp.int-x3.letsencrypt.org 解析的 IP 地址,把解析到的第1个 IP 追加到 /etc/hosts 文件里。如:

$ cat /etc/hosts
127.0.0.1 VM_0_10_centos VM_0_10_centos
127.0.0.1 localhost.localdomain localhost
127.0.0.1 localhost4.localdomain4 localhost4

#手动添加解析
23.215.104.25 ocsp.int-x3.letsencrypt.org

::1 VM_0_10_centos VM_0_10_centos
::1 localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6

再次执行 certbot-auto renew 输出如下:

$ certbot-auto renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/yangdx.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/yangdx.com/fullchain.pem expires on 2020-11-20 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

因为我的证书是刚申请下来的,执行 certbot-auto renew 暂时不会续期,只有临近过期时间在 30 天以内的证书才会被续期。

证书续期成功后,请记得要重启 Nginx 服务。