Let's Encrypt

Let’s Encrypt 是一个认证机构(Certificate Authority = CA)

想使用 HTTPS 需要认证机构颁发的电子证书

Let’s Encrypt 和其他认证机构的区别(或者说是卖点):

  • 免费,Let’s Encrypt 提供期限是90天的免费电子证书
  • 提供工具 certbot 自动生成电子证书文件

Let’s Encrypt为了自动生成电子证书搞了一个 ACME协议

  • Automatic Certificate Management Environment=ACME,自动认证管理环境协议
  • 协议草案已经提交IETF
  • ACME协议的基本思路是:
    • 在你服务器上生成一次性的随机特征数据(nonce)
    • 然后通过Let’s Encrypt的服务器核对这个数据
    • 核对成功发放证书
    • 有两种方式,HTTP和DNS,一般使用的是前者

安装 Certbot

certbot 是 let‘s encrypt 官方提供的一个工具。

安装方式参考官方的文档:官方文档

首先需要安装 snapd,之后通过 snap 来安装 certbot。

本文是在 centos 7.6 系统中安装的,所以在安装界面选择 centos

certbot-前置安装snapd

点进去之后根据文档提示进行安装,命令如下:

  • 安装 epel 源
1
2
3
4
5
# centos 7
sudo yum install epel-release
# centos 8
sudo dnf install epel-release
sudo dnf upgrade
  • 安装 snapd
1
sudo yum install snapd
  • 设置 snapd.socket 为开机自动启动
1
sudo systemctl enable --now snapd.socket
  • 启用经典snap支持,安装 certbot 必须执行此命令,否则报错。
1
sudo ln -s /var/lib/snapd/snap /snap

安装完 snapd 之后,开始正式安装 certbot。

1
2
3
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

ACME 验证方式

前面提到 ACME 协议有个核对数据的过程,核对方式有两种 HTTP 和 DNS。

其中 HTTP 方式只能验证三级域名或者三级以上的域名。示例:www.example.comdemo.api.example.com

DNS 方式除了可以验证三级域名或者三级以上,还可以验证泛域名或者说通配符域名。示例:*.example.com

HTTP 方式验证又分为下面两种方式:

  • webroot:网站根目录验证方式,申请证书时不需要暂停现有的网站。当然我们修改完成配置然后需要启用 https 配置还是需要重新启动服务的。
  • standalone:不需要指定网站根目录,他会自动启用服务器的80端口来验证。如果其他服务占用了 80 端口,就必须先停止这些服务,在证书生成完毕后,再启用。

网站域名证书申请(常用)

通常我们申请证书只是给单个网站域名或者少量域名使用,并且我们的网站使用的是 nginx 这种网站服务器时,我们可以简单点直接使用 http 验证方式中的 webroot 方式。如果我们的网站不是 nginx 这种网站服务器时,比如程序直接启动的 WebServer 或者 微服务 等,就没办法使用 webroot 了。就需要使用 standalone。

webroot 配置方式

网站服务器使用:nginx,nginx 为官网源码编译版本。其他 yum 或者 apt 安装的 nginx 使用相同

创建验证需求的配置

在 nginx 程序目录创建 certbot文件夹,当然你也可以放到别处

创建验证配置文件:touch /root/nginx/certbot/letsencrypt.conf

1
2
3
4
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt; # 这个路径就是 ACME 在验证请求证书时访问的文件目录位置
}

创建配置文件需要的目录:

1
sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge

创建 ssl 配置文件

创建配置文件:touch /root/nginx/certbot/ssl.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

ssl_protocols TLSv1.2;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;

add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

修改 http 网站配置

找到你自己网站的配置文件。这一步是让 ACME可以验证你接下来的证书申请请求。

本文:/root/nginx/conf/conf.d/example.com

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name www.example.com;

include /root/nginx/certbot/letsencrypt.conf; # 需要增加的内容

root /var/www/www.example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}

配置好后重新加载 nginx,使其生效

1
2
3
nginx -s reload 
# 或者
systemctl reload nginx

申请证书

执行下面的命令发送域名证书申请,注意修改参数。如果想一个证书给多个域名使用,可以重复使用-d参数追加域名,比如 nginx 只是用来代理转发,那么就可以把所有的域名使用 -d追加上

1
2
3
4
5
certbot certonly --webroot --agree-tos --no-eff-email \
--email yourname@example.com \
-w /var/www/letsencrypt \
-d www.example.com
# -d xxx.example.com

执行示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@tencent ~]# certbot certonly --webroot --agree-tos --no-eff-email --email xxxxxxx@qq.com -w /var/www/letsencrypt -d www.example.com
ERROR: ld.so: object '/$LIB/libonion.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for www.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/www.example.com/fullchain.pem # 证书保存位置
Key is saved at: /etc/letsencrypt/live/www.example.com/privkey.pem # 私玥保存位置
This certificate expires on 2022-11-07.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@tencent ~]#

在申请结果中提示了我们证书的保存位置,下面我们就需要把相关配置配置到我们的网站配置中。

配置网站 https

在我们原网站配置文件中追加一个监听 443 端口的 server 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 原网站配置,修改下使其强制跳转 https 访问
server {
listen 80;
server_name www.example.com;
include /root/nginx/certbot/letsencrypt.conf;
location / {
return 301 https://www.example.com$request_uri;
}
# root /var/www/www.example.com;
# access_log /var/log/nginx/example.log;
}

# 新的追加配置
server {
server_name www.example.com;
listen 443 ssl;
listen [::]:443 ssl;

# 追加 ssl 证书配置
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
include /root/nginx/certbot/ssl.conf;

root /var/www/www.example.com;
access_log /var/log/nginx/example_https.log;
}

配置好之后重启 nginx,访问测试

1
2
3
nginx -s reload 
# 或者
systemctl reload nginx

续期证书

执行下面的命令会自动检查本地的证书是否可以续期。如果可以的话会自动做续期处理,续期成功后需要重新 nginx 服务。可以做个脚本挂计划任务定期执行。证书的有效期为 90 天。

1
certbot renew

如果是通配符域名,使用 dns 验证的。续期时需要使用下面的命令:

1
certbot certonly --manual -d '*.example.com'

会提示你和申请证书一样的流程,需要更改域名下一个 txt 记录,如下过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@VM-xVO5pN310rIk ~]# certbot certonly --manual -d '*.chilisdy.site'
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Renewing an existing certificate for *.chilisdy.site

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_acme-challenge.chilisdy.site.

with the following value:

uTJNjsiQBnd_Lhaj0mALRr7MICvInBSyuc-Wi7iOObw

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.chilisdy.site.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/chilisdy.site/fullchain.pem
Key is saved at: /etc/letsencrypt/live/chilisdy.site/privkey.pem
This certificate expires on 2023-03-19.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@VM-xVO5pN310rIk ~]#

查看已申请证书

1
certbot certificates

删除证书

注意:不要直接删除文件方式去删除证书

1
certbot delete --cert-name example.com

删除示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@tencent conf.d]# certbot certificates
ERROR: ld.so: object '/$LIB/libonion.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: chilisdy.site # 删除命令后面指定的名称为这里的名称
Serial Number: 4f9073372b33897abf92f51dc71cb7e78cf
Key Type: RSA
Domains: *.chilisdy.site
Expiry Date: 2022-11-07 08:01:20+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/chilisdy.site/fullchain.pem
Private Key Path: /etc/letsencrypt/live/chilisdy.site/privkey.pem

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@tencent conf.d]# certbot delete --cert-name chilisdy.site # 删除命令
ERROR: ld.so: object '/$LIB/libonion.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificate(s) are selected for deletion:

* chilisdy.site

WARNING: Before continuing, ensure that the listed certificates are not being
used by any installed server software (e.g. Apache, nginx, mail servers).
Deleting a certificate that is still being used will cause the server software
to stop working. See https://certbot.org/deleting-certs for information on
deleting certificates safely.

Are you sure you want to delete the above certificate(s)?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
Deleted all files relating to certificate chilisdy.site.
[root@tencent conf.d]#

standalone 配置方式

此方式和 webroot 方式的不同之处:

  • 申请证书期间需要停止 80 端口的服务
  • 80 端口部分的服务配置不需要提供 webroot 验证目录
  • 申请证书的命令不同,命令如下:
1
2
3
4
certbot certonly --standalone --agree-tos --no-eff-email \
--email xxxxx@qq.com \
-d demo1.example.site \
-d demo2.example.site

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@tencent ~]# certbot certonly --standalone --agree-tos --no-eff-email --email xxxxx@qq.com -d demo1.example.site -d demo2.example.site
ERROR: ld.so: object '/$LIB/libonion.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for demo1.example.site and demo2.example.site

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/demo1.example.site/fullchain.pem
Key is saved at: /etc/letsencrypt/live/demo1.example.site/privkey.pem
This certificate expires on 2022-11-07.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@tencent ~]#

申请证书之后,同上面的配置网站部分操作相同。

下面给出本文另一个 nginx 代理网站的 https 配置文件,注意 80 端口配置并没有提供 webroot 验证目录配置,在本文也就是没有include /root/nginx/certbot/letsencrypt.conf;配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 还是一样 80 端口部分做强制跳转 https
server {
listen 80;
server_name image.chilisdy.site;

location / {
return 301 https://image.chilisdy.site$request_uri;
}
}


server {
server_name image.chilisdy.site;
listen 443 ssl;
listen [::]:443 ssl;

ssl_certificate /etc/letsencrypt/live/image.chilisdy.site/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/image.chilisdy.site/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/image.chilisdy.site/fullchain.pem;
include /root/nginx/snippets/ssl.conf;

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

通配符(泛域名)证书申请

通配符(泛域名)证书申请只能使用 DNS 验证的方式,证书申请下来之后直接配置到服务中即可,泛域名可以给此域名下的所有域名使用。

DNS 申请步骤如下:

  1. 执行证书申请命令。-d后面的参数为你的域名
1
certbot certonly --manual --preferred-challenges dns -d "*.chilisdy.site"
  1. 这时候命令行中会显示你需要配置的 DNS 信息,这时候会卡在这里,千万不要继续按回车。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@tencent conf.d]# certbot certonly --manual --preferred-challenges dns -d "*.chilisdy.site"
ERROR: ld.so: object '/$LIB/libonion.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for *.chilisdy.site

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_acme-challenge.chilisdy.site.

with the following value:

4ate8hXZYsFJkZMB0CZBOd9iy3bV73BGMnpusMUgrHA

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.chilisdy.site.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

我们只需要在控制台配置一条 TXT 记录,然后验证生效后在按回车继续。

配置 TXT 记录示例:

TXT配置示例

使用下面的命令进行验证是否生效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
➜  ~ dig -t txt _acme-challenge.chilisdy.site

; <<>> DiG 9.10.6 <<>> -t txt _acme-challenge.chilisdy.site
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16968
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;_acme-challenge.chilisdy.site. IN TXT

;; ANSWER SECTION:
_acme-challenge.chilisdy.site. 600 IN TXT "4ate8hXZYsFJkZMB0CZBOd9iy3bV73BGMnpusMUgrHA"

;; Query time: 27 msec
;; SERVER: 114.114.114.114#53(114.114.114.114)
;; WHEN: Tue Aug 09 17:01:09 CST 2022
;; MSG SIZE rcvd: 103

➜ ~

正确显示信息后按回车继续申请。

申请成功示例如下:

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

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/chilisdy.site/fullchain.pem
Key is saved at: /etc/letsencrypt/live/chilisdy.site/privkey.pem
This certificate expires on 2022-11-07.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@tencent conf.d]#

这里同样拿到两个证书。使用配置方法和本文 HTTP 验证部分完全一致。