如何在Debian8上使用Let'sEncrypt保护Nginx

来自菜鸟教程
跳转至:导航、​搜索

介绍

Let's Encrypt 是一个新的证书颁发机构 (CA),它提供了一种简单的方法来获取和安装免费的 TLS/SSL 证书,从而在 Web 服务器上启用加密的 HTTPS。 它通过提供软件客户端 certbot(以前称为 letsencrypt)来简化流程,该客户端尝试自动化大部分(如果不是全部)所需步骤。 目前,获取和安装证书的整个过程仅在 Apache Web 服务器上是完全自动化的。 但是,使用 Let's Encrypt 可以轻松获得免费的 SSL 证书,无论您选择何种 Web 服务器软件,都可以手动安装该证书。

在本教程中,我们将向您展示如何使用 Let's Encrypt 获得免费的 SSL 证书并将其与 Debian 8 上的 Nginx 一起使用。 我们还将向您展示如何自动更新您的 SSL 证书。 如果您正在运行不同的 Web 服务器,只需按照您的 Web 服务器的文档来了解如何在您的设置中使用证书。

先决条件

在学习本教程之前,您需要做一些事情。

您应该拥有一个 Debian 8 服务器,其中的非 root 用户具有 sudo 权限。 您可以按照我们的 Debian 8 初始服务器设置教程 学习如何设置这样的用户帐户。

如果您尚未在服务器上安装 Nginx,请按照 本指南 进行安装。

您必须拥有或控制您希望使用证书的注册域名。 如果您还没有注册域名,您可以在众多域名注册商之一注册一个(例如 Namecheap、GoDaddy 等)。

如果您还没有,请务必创建一个 A 记录,将您的域指向您服务器的公共 IP 地址(如果您使用 DigitalOcean 的 DNS,您可以按照 本指南 [X194X ])。 这是必需的,因为 Let's Encrypt 如何验证您是否拥有它为其颁发证书的域。 例如,如果您想获得 example.com 的证书,则该域必须解析到您的服务器,验证过程才能正常工作。 我们的设置将使用 example.comwww.example.com 作为域名,因此需要 两个 DNS 记录

完成所有先决条件后,让我们继续安装 Let's Encrypt 客户端软件。

第 1 步:安装 Certbot,Let's Encrypt 客户端

使用 Let's Encrypt 获取 SSL 证书的第一步是在您的服务器上安装 certbot Let's Encrypt 客户端。

certbot 软件包在 Debian 8 发布时不可用。 要访问 certbot 包,我们必须在我们的服务器上启用 Jessie backports 存储库。 此存储库可用于安装比稳定存储库中包含的更新版本的软件。

通过键入以下内容将 backports 存储库添加到您的服务器:

echo 'deb http://ftp.debian.org/debian jessie-backports main' | sudo tee /etc/apt/sources.list.d/backports.list

添加新存储库后,更新 apt 包索引以下载有关新包的信息:

sudo apt-get update

更新存储库后,您可以通过定位 backports 存储库来安装 certbot 包:

注意: 使用 backports 时,建议只安装您需要的特定包,而不是使用存储库进行一般更新。 与主存储库相比,反向移植包的兼容性保证更少。

为了帮助避免使用此存储库意外安装或更新软件包,您必须显式传递带有存储库名称的 -t 标志以从后端安装软件包。


sudo apt-get install certbot -t jessie-backports

certbot 客户端现在应该可以使用了。

第 2 步:获取 SSL 证书

Let's Encrypt 通过各种插件提供了多种获取 SSL 证书的方法。 与 另一个教程 中介绍的 Apache 插件不同,大多数插件只会帮助您获得必须手动配置 Web 服务器才能使用的证书。 只获取证书而不安装它们的插件被称为“身份验证器”,因为它们用于验证是否应该向服务器颁发证书。

我们将向您展示如何使用 Webroot 插件来获取 SSL 证书。

如何使用 Webroot 插件

Webroot 插件通过在文档根目录中的 /.well-known 目录中放置一个特殊文件来工作,Let's Encrypt 服务可以(通过您的 Web 服务器)打开该文件以进行验证。 根据您的配置,您可能需要明确允许访问 /.well-known 目录。

如果您还没有安装 Nginx,请按照 本教程 进行安装。 完成后继续往下看。

为了确保 Let's Encrypt 可以访问该目录以进行验证,让我们快速更改我们的 Nginx 配置。 默认情况下,它位于 /etc/nginx/sites-available/default。 我们将使用 nano 来编辑它:

sudo nano /etc/nginx/sites-available/default

在 server 块中,添加这个 location 块:

添加到 SSL 服务器块

        location ~ /.well-known {
                allow all;
        }

您还需要通过搜索 root 指令来查找文档根目录的设置,因为使用 Webroot 插件需要该路径。 如果您使用默认配置文件,则根目录为 /var/www/html

保存并退出。

检查您的配置是否有语法错误:

sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

如果没有发现错误,请使用以下命令重新启动 Nginx:

sudo systemctl restart nginx

现在我们知道了我们的 webroot-path,我们可以使用 Webroot 插件通过这些命令请求 SSL 证书。 在这里,我们还使用 -d 选项指定我们的域名。 如果您希望单个证书与多个域名一起使用(例如 example.comwww.example.com),请务必包括所有这些。 此外,请确保将突出显示的部分替换为适当的 webroot 路径和域名:

sudo certbot certonly -a webroot --webroot-path=/var/www/html -d example.com -d www.example.com

certbot 初始化后,系统会提示您输入您的电子邮件并同意 Let's Encrypt 服务条款。 之后,挑战将运行。 如果一切顺利,您应该会看到如下所示的输出消息:

Output:IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert
   will expire on 2017-09-05. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you lose your account credentials, you can recover through
   e-mails sent to sammy@example.com.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - 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

您需要注意证书的路径和到期日期,这在示例输出中突出显示。

防火墙 注意: 如果您收到类似 Failed to connect to host for DVSNI challenge 的错误,您的服务器的防火墙可能需要配置为允许端口 80443 上的 TCP 流量。

注意: 如果您的域通过 CloudFlare 等 DNS 服务进行路由,您需要暂时禁用它,直到您获得证书。


证书文件

获得证书后,您将拥有以下 PEM 编码文件:

  • cert.pem: 你的域名证书
  • chain.pem: Let's Encrypt 链证书
  • 全链.pem: cert.pem and chain.pem combined
  • privkey.pem: 你证书的私钥

了解刚刚创建的证书文件的位置很重要,因此您可以在 Web 服务器配置中使用它们。 文件本身放置在 /etc/letsencrypt/archive 的子目录中。 但是,Let's Encrypt 会在 /etc/letsencrypt/live/your_domain_name 目录中创建指向最新证书文件的符号链接。 因为链接将始终指向最新的证书文件,所以您应该使用该路径来引用您的证书文件。

您可以通过运行以下命令检查文件是否存在(替换为您的域名):

sudo ls -l /etc/letsencrypt/live/your_domain_name

输出应该是前面提到的四个证书文件。 稍后,您将配置您的 Web 服务器以使用 fullchain.pem 作为证书文件,并将 privkey.pem 作为证书密钥文件。

生成强 Diffie-Hellman 群

为了进一步提高安全性,您还应该生成一个强大的 Diffie-Hellman 组。 要生成 2048 位组,请使用以下命令:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

这可能需要几分钟,但完成后您将在 /etc/ssl/certs/dhparam.pem 拥有一个强大的 DH 组。

第 3 步:在 Web 服务器 (Nginx) 上配置 TLS/SSL

现在您有了 SSL 证书,您需要配置您的 Nginx Web 服务器以使用它。

我们将对我们的配置进行一些调整:

  1. 我们将创建一个包含我们的 SSL 密钥和证书文件位置的配置片段。
  2. 我们将创建一个包含强 SSL 设置的配置片段,将来可以与任何证书一起使用。
  3. 我们将调整 Nginx 服务器块来处理 SSL 请求并使用上面的两个片段。

这种配置 Nginx 的方法将允许我们保持干净的服务器块并将常见的配置段放入可重用的模块中。

创建指向 SSL 密钥和证书的配置片段

首先,让我们在 /etc/nginx/snippets 目录下新建一个 Nginx 配置片段。

为了正确区分该文件的用途,我们将其命名为 ssl-,后跟我们的域名,最后是 .conf

sudo nano /etc/nginx/snippets/ssl-example.com.conf

在此文件中,我们只需将 ssl_certificate 指令设置为我们的证书文件,并将 ssl_certificate_key 设置为关联的密钥。 在我们的例子中,这将如下所示:

/etc/nginx/snippets/ssl-example.com.conf

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

添加这些行后,保存并关闭文件。

创建具有强加密设置的配置片段

接下来,我们将创建另一个片段来定义一些 SSL 设置。 这将为 Nginx 设置一个强大的 SSL 密码套件,并启用一些有助于保持我们服务器安全的高级功能。

我们将设置的参数可以在未来的 Nginx 配置中重复使用,因此我们将给文件一个通用名称:

sudo nano /etc/nginx/snippets/ssl-params.conf

为了安全地设置 Nginx SSL,我们将使用 Cipherli.st 站点上 Remy van Elst 的建议。 该站点旨在为流行软件提供易于使用的加密设置。 您可以在 此处 阅读有关他对 Nginx 选择的决定的更多信息。

注意: Cipherli.st 上的默认建议设置提供了强大的安全性。 有时,这是以更高的客户端兼容性为代价的。 如果您需要支持旧客户端,可以通过单击链接上标有“是的,给我一个适用于旧版/旧软件的密码套件”的链接访问一个替代列表。

可以使用兼容性列表代替下面配置中的默认建议。 您使用哪种配置的选择很大程度上取决于您需要支持什么。


出于我们的目的,我们可以完整地复制提供的设置。 我们只需要做一些小的修改。

首先,我们将为上游请求添加首选 DNS 解析器。 我们将在本指南中使用 Google 的。 我们还将继续设置 ssl_dhparam 设置以指向我们之前生成的 Diffie-Hellman 文件。

最后,您应该花点时间阅读 HTTP Strict Transport Security 或 HSTS,特别是 “预加载”功能 。 预加载 HSTS 可提高安全性,但如果意外启用或启用不正确,可能会产生深远的影响。 在本指南中,我们不会预加载设置,但如果您确定了解其中的含义,您可以对其进行修改:

/etc/nginx/snippets/ssl-params.conf

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

完成后保存并关闭文件。

调整 Nginx 配置以使用 SSL

现在我们有了代码片段,我们可以调整 Nginx 配置以启用 SSL。

我们将在本指南中假设您正在使用 /etc/nginx/sites-available 目录中的 default 服务器块文件。 如果您使用不同的服务器块文件,请在以下命令中替换其名称。

在我们继续之前,让我们备份我们当前的服务器块文件:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

现在,打开服务器块文件进行调整:

sudo nano /etc/nginx/sites-available/default

在内部,您的服务器块可能像这样开始:

/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    . . .

我们将修改此配置,以便未加密的 HTTP 请求自动重定向到加密的 HTTPS。 这为我们的网站提供了最好的安全保障。 如果您希望同时允许 HTTP 和 HTTPS 流量,请使用以下替代配置。

我们将把配置分成两个单独的块。 在前两个 listen 指令之后,我们将添加一个 server_name 指令,设置为您服务器的域名。 然后,我们将设置重定向到我们将创建的第二个服务器块。 之后,我们将关闭这个短块:

/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    . . .

接下来,我们需要在下面直接启动一个新的服务器块来包含剩余的配置。 我们可以取消注释使用端口 443 的两个 listen 指令。 之后,我们只需要包含我们设置的两个片段文件:

注意: 您可能只有 一个 listen 指令,其中包括每个 IP 版本和端口组合的 default_server 修饰符。 如果您为这些设置了 default_server 的端口启用了其他服务器块,则必须从其中一个块中删除修饰符。


/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {

    # SSL configuration

    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    . . .

完成后保存并关闭文件。

(替代配置)允许 HTTP 和 HTTPS 流量

如果您希望或需要同时允许加密和未加密的内容,则必须对 Nginx 进行一些不同的配置。 如果可以避免,通常不建议这样做,但在某些情况下可能需要这样做。 基本上,我们只是将两个单独的服务器块压缩为一个块并删除重定向:

/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name example.com www.example.com;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    . . .

完成后保存并关闭文件。

第四步:调整防火墙

如果您启用了防火墙,则需要调整设置以允许 SSL 流量。 所需的过程取决于您使用的防火墙软件。 如果您当前没有配置防火墙,请随时跳过。

UFW

如果您使用 ufw,您可以通过键入以下内容查看当前设置:

sudo ufw status

它可能看起来像这样,这意味着只允许 HTTP 流量进入 Web 服务器:

OutputStatus: active

To                         Action      From
--                         ------      ----
SSH                        ALLOW       Anywhere
WWW                        ALLOW       Anywhere
SSH (v6)                   ALLOW       Anywhere (v6)
WWW (v6)                   ALLOW       Anywhere (v6)

为了额外允许 HTTPS 流量,我们可以允许“WWW Full”配置文件,然后删除多余的“WWW”配置文件允许:

sudo ufw allow 'WWW Full'
sudo ufw delete allow 'WWW'

您的状态现在应该如下所示:

sudo ufw status
OutputStatus: active

To                         Action      From
--                         ------      ----
SSH                        ALLOW       Anywhere
WWW Full                   ALLOW       Anywhere
SSH (v6)                   ALLOW       Anywhere (v6)
WWW Full (v6)              ALLOW       Anywhere (v6)

您的服务器现在应该接受 HTTPS 请求。

IPTables

如果您使用 iptables,您可以通过键入以下内容查看当前规则:

sudo iptables -S

如果您启用了任何规则,它们将被显示。 示例配置可能如下所示:

Output-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

打开 SSL 流量所需的命令取决于您当前的规则。 对于像上面这样的基本规则集,您可以通过键入以下内容添加 SSL 访问:

sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT

如果我们再次查看防火墙规则,我们应该会看到新规则:

sudo iptables -S
Output-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

如果您使用程序在启动时自动应用 iptables 规则,您需要确保使用新规则更新您的配置。

第 5 步:启用 Nginx 中的更改

现在我们已经进行了更改并调整了防火墙,我们可以重新启动 Nginx 以实施我们的新更改。

首先,我们应该检查以确保我们的文件中没有语法错误。 我们可以通过键入:

sudo nginx -t

如果一切顺利,您将得到如下所示的结果:

Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

如果您的输出与上述匹配,则您的配置文件没有语法错误。 我们可以安全地重启 Nginx 来实现我们的更改:

sudo systemctl restart nginx

Let's Encrypt TLS/SSL 证书现已到位,防火墙现在允许流量到端口 80 和 443。 此时,您应该通过在 Web 浏览器中通过 HTTPS 访问您的域来测试 TLS/SSL 证书是否有效。

您可以使用 Qualys SSL 实验室报告查看您的服务器配置得分:

In a web browser:https://www.ssllabs.com/ssltest/analyze.html?d=example.com

这可能需要几分钟才能完成。 本指南中的 SSL 设置应至少报告 A 等级。

第 6 步:设置自动续订

Let's Encrypt 证书的有效期为 90 天,但建议您每 60 天更新一次证书,以允许存在误差。 在撰写本文时,自动续订仍不能作为客户端本身的一项功能,但您可以通过运行带有 renew 选项的 Let's Encrypt 客户端手动续订证书。

要触发所有已安装域的续订过程,请运行以下命令:

sudo certbot renew

因为我们最近安装了证书,所以该命令只会检查到期日期并打印一条消息,通知证书尚未到期续订。 输出应与此类似:

Output:Saving debug log to /var/log/letsencrypt/example.com.log

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

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/example.com/fullchain.pem (skipped)
No renewals were attempted.

请注意,如果您创建了包含多个域的捆绑证书,则输出中将仅显示基本域名,但续订应对该证书中包含的所有域都有效。

确保您的证书不会过时的一种实用方法是创建一个 cron 作业,该作业将定期为您执行自动更新命令。 由于续订首先检查到期日期,并且仅在证书距离到期不到 30 天时才执行续订,因此可以安全地创建一个每周甚至每天运行的 cron 作业。

让我们编辑 crontab 以创建一个每周运行更新命令的新作业。 要为 root 用户编辑 crontab,请运行:

sudo crontab -e

如果这是您第一次使用 crontab,您可能会被要求选择您喜欢的文本编辑器。 如果您没有强烈的偏好,nano 是一个简单的选择。

添加以下行:

crontab entry30 2 * * * /usr/bin/certbot renew --noninteractive --renew-hook "/bin/systemctl reload nginx" >> /var/log/le-renew.log

保存并退出。 这将创建一个新的 cron 作业,该作业将在每天凌晨 2:30 执行 certbot renew 命令,并在更新证书时重新加载 Nginx。 该命令产生的输出将通过管道传送到位于 /var/log/le-renewal.log 的日志文件。

注意: 有关如何创建和安排 cron 作业的更多信息,您可以查看我们的 如何在 VPS 指南中使用 Cron 自动执行任务。


结论

就是这样! 您的 Web 服务器现在使用免费的 Let's Encrypt TLS/SSL 证书来安全地提供 HTTPS 内容。