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

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

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

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

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

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

创建 ssl 配置文件

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

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

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,使其生效

nginx -s reload 
# 或者
systemctl reload nginx

申请证书

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

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

执行示例如下:

[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 配置:

# 原网站配置,修改下使其强制跳转 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,访问测试

nginx -s reload 
# 或者
systemctl reload nginx

续期证书

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

certbot renew

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

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

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

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

查看已申请证书

certbot certificates

删除证书

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

certbot delete --cert-name example.com

删除示例:

[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 验证目录
  • 申请证书的命令不同,命令如下:
certbot certonly --standalone --agree-tos --no-eff-email \
--email xxxxx@qq.com \
-d demo1.example.site \
-d demo2.example.site

示例:

[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;配置。

# 还是一样 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后面的参数为你的域名
certbot certonly --manual --preferred-challenges dns -d "*.chilisdy.site"
  1. 这时候命令行中会显示你需要配置的 DNS 信息,这时候会卡在这里,千万不要继续按回车。
[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配置示例

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

➜  ~ 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

➜  ~

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

申请成功示例如下:


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 验证部分完全一致。