使用 Let's Encrypt 和 certbot 免费申请 SSL 证书

本文详细介绍如何使用 Let's Encrypt 和 Certbot 免费申请 SSL 证书,并实现自动申请、自动部署以及自动续约。

使用 Let's Encrypt 和 certbot 免费申请 SSL 证书

工具安装

Let’s Encrypt 介绍

Let’s Encrypt 是一个免费、自动化、开放的证书颁发机构 (CA),为网站提供数字证书以启用 HTTPS ( SSL/TLS )。它的存在解决了获取、安装和维护证书的复杂性,从而为每个网站提供了一个安全的互联网。

Let’s Encrypt 的主要特点:

  1. 免费的: Let’s Encrypt 提供的 SSL/TLS 证书完全免费。这大大降低了启用 HTTPS 的门槛。
  2. 自动化: Let’s Encrypt 的设计和协议(即 ACME ,自动证书管理环境)允许服务器的自动化配置,简化了证书的获取、安装和续订过程。
  3. 安全:尽管 Let’s Encrypt 的证书是免费的,但它们提供与其他商业 CA 相同级别的安全性。
  4. 短期证书: Let’s Encrypt 颁发的证书有效期为 90 天。虽然这远远短于许多其他 CA 的有效期,但由于自动续订的能力,这通常不是问题。事实上,这种短期有效性提供了更高的安全性,因为证书的滥用时间减少了。
  5. 背景与支持: Let’s Encrypt 是由 Internet Security Research Group (ISRG) 启动的。它得到了许多大公司和组织的支持,例如 Mozilla 、 Cisco 、 Electronic Frontier Foundation (EFF)、 Google Chrome 、 Facebook 等。

Certbot 工具介绍

Certbot 是一个免费的、开源的命令行工具。它可以极大的简化我们为网站启用 HTTPS 的过程,它提供自动化获取、安装、续订和管理 Let’s Encrypt 提供的 SSL/TLS 证书的功能。

Certbot 和 Let’s Encrypt 的关系

Let’s Encrypt 是一个证书颁发机构( CA ),它提供免费的 SSL/TLS 证书,而 Certbot 是一个工具,用于自动化地从 Let’s Encrypt 获取、安装和管理这些证书。

安装 Certbot

Certbot 的安装方法取决于你的操作系统和包管理器。

在 Ubuntu 上使用 apt 安装:

sudo apt-get update
sudo apt-get install certbot

在 CentOS 上使用 yum 安装:

sudo yum install certbot

对于其他操作系统和包管理器,请参考 Certbot 的官方文档

自动申请证书 [自动验证,自动部署,自动续约]

自动申请的限制

自动申请证书只能用于单个域名,不能申请泛域名。因为泛域名申请必须使用 DNS 验证,所以必须手动验证。

虽然可以通过一些格外的配置来支持泛域名,但是比较复杂,并且对 DNS 服务商也存在限制,这里先不考虑。

自动申请原理 & Certbot 插件安装

使用 certbot 可以实现自动申请证书,并在证书到期后自动续约 SSL 证书,但是需要安装格外的插件。

实现的原理如下:

  1. 自动化的域名验证:
    当你使用 certbot 的 Web 服务器插件(如 --nginx 或 --apache),工具会自动配置服务器以满足 Let’s Encrypt 的域名验证要求。这是通过对服务器进行临时配置来响应 ACME 挑战来完成的。
  2. 证书的获取与安装:
    一旦域名成功验证,certbot 会从 Let’s Encrypt 的服务器下载证书文件,并在适当的位置自动配置它们,以便 Web 服务器可以使用这些证书。
  3. 续约检查:
    certbot 具有一个内部机制,定期(通常每天)检查已安装证书的有效期。默认情况下,如果证书距到期时间少于 30 天,certbot 将尝试自动续约。
  4. 自动续约:
    证书续约的过程与初次申请证书类似,但更快,因为大多数配置都已经就位。certbot 会再次执行域名验证,然后获取新的证书替换旧的证书。

通过这些机制,certbot 能够为用户提供几乎无缝的证书管理体验,大大减少了手动维护和续约证书的需求。

需要根据你使用的 Web 来安装相应的插件,下面以 CentOS 上安装作为演示:

如果使用 Nginx 作为服务器,需要安装 nginx 插件:

sudo yum install python2-certbot-nginx

如果使用 Apache 作为服务器,需要安装 apache 插件:

sudo yum install python2-certbot-apache

自动申请操作步骤

对于 Nginx :

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

对于 Apache :

sudo certbot --apache -d yourdomain.com -d www.yourdomain.com

这将自动为你的域名获取证书,然后还会自动修改 Web 服务器的配置以使用新的证书,并为证书设置自动续约。

自动续约

当你使用上述命令成功申请证书后,它会自动设置一个 cron 或 systemd job 来尝试自动续约证书。

你可以通过运行以下命令来测试自动续约是否工作:

sudo certbot renew --dry-run

如果一切正常,这将模拟续约过程并显示任何可能的问题。在正常情况下,certbot 将每天检查一次证书,并在其有效期少于 30 天时尝试续约。

手动申请证书 [手动验证,手动部署,手动续约]

申请泛域名证书

泛域名证书的限制

泛域名证书可以用于保护域名下的所有子域名。例如,一个 *.yourdomain.com 的泛域名证书可以用于保护 sub1.yourdomain.comsub2.yourdomain.com 等等。

你可以使用 Certbot 来申请一个泛域名 (wildcard) 证书,但是存在一些限制条件:

  1. 泛域名只能使用 DNS 验证,需要你在 DNS 中添加一个特定的记录,因此只能手动申请。

因为泛域名涵盖了所有可能的子域,所以使用 HTTP-01 验证(即通过你的 web 服务器验证)是不切实际的。因此,你需要使用 DNS-01 验证,这意味着为了验证你对域名的控制权,你需要在 DNS 中添加一个特定的记录。

  1. 泛域名不支持到期自动续约,到期后需要手动再次申请。

也可以通过一些格外的配置来支持,但是比较复杂,并且对 DNS 服务商也存在限制,这里先不考虑。

手动申请步骤

使用 以下命令申请泛域名证书:

sudo certbot certonly --manual --preferred-challenges=dns -d "*.yourdomain.com"

命令解释:

  • certonly: 这个子命令告诉 certbot 仅获取证书,而不尝试自动配置任何服务器来使用它。
  • --manual: 这个选项表示证书的获取和验证过程将由用户手动完成。
  • --preferred-challenges=dns: 这指定了 certbot 应该使用 DNS 验证你对指定域名的控制权。这意味着你需要为你的域名添加一个特定的 DNS TXT 记录,以证明你对该域名有控制权。

执行上述命令后, Certbot 会提供一些提示,告诉你如何在 DNS 记录中添加一个特定的 TXT 记录:

image-20230819204559502

你需要在你的域名提供商处添加一条 TXT 解析记录,这会用于验证你对这个域名的所有权:

image-20230819211745991

添加完成之后,回到终端,按回车确认。若验证通过,将会自动签发并下载证书文件:

image-20230819205830402

证书文件将保存在红框部分,其他 privkey.pem 为私钥, fullchain.pem 为完整证书。

如果你使用手动的方式,接下来就需要手动在 Nginx 中安装证书,安装方法请参考【安装证书: Nginx 】。

申请单个域名证书

要使用 certbot 手动申请一个单一域名的证书(而不是泛域名),你可以使用类似的命令,但简化了域名部分。

使用 DNS 验证(这是我最推荐的方式,简单命令,不容易出错):

sudo certbot certonly --manual --preferred-challenges=dns -d www.yourdomain.com

在执行此命令后,certbot 将提供一个特定的 DNS TXT 记录,你需要将它添加到你的域名的 DNS 设置中以完成验证,然后即可自动完成证书签发以及下载。

如果你使用手动的方式,接下来就需要手动在 Nginx 中安装证书,安装方法请参考【安装证书: Nginx 】。

安装证书: Nginx

如果你采用手动的方式申请 SSL 证书,申请完成后,我们需要将它安装到 Nginx 上,才能让 HTTPS 生效。

打开你的 Nginx 配置文件,这通常位于 /etc/nginx/nginx.conf ,在 server 块中,你需要指定以下两个指令:

ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem;
image-20230819211200543

确保你的 server 块监听了 443 端口(这是 HTTPS 的默认端口):

listen 443 ssl;

保存并关闭配置文件,检查 Nginx 配置是否有误:

sudo nginx -t

如果一切正常,你应该看到 syntax is okay 和 test is successful 的消息。

最后,重新加载 Nginx 以应用更改:

sudo systemctl reload nginx

现在,你的 Nginx 服务器应该已经成功配置为使用 SSL/TLS 证书,并能够安全地处理 HTTPS 请求。