如何在Ubuntu16.04中为Nginx创建自签名SSL证书

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

介绍

TLS 或传输层安全性及其前身 SSL 代表安全套接字层,是用于将正常流量包装在受保护的加密包装器中的 Web 协议。

使用这项技术,服务器可以在服务器和客户端之间安全地发送流量,而不会被外界截获消息。 证书系统还帮助用户验证他们正在连接的站点的身份。

在本指南中,我们将向您展示如何设置自签名 SSL 证书以在 Ubuntu 16.04 服务器上与 Nginx Web 服务器一起使用。

注意: 自签名证书将加密您的服务器和任何客户端之间的通信。 但是,由于它没有由 Web 浏览器中包含的任何受信任的证书颁发机构签名,因此用户无法使用该证书自动验证您的服务器的身份。

如果您没有与您的服务器关联的域名,并且在加密的 Web 界面不是面向用户的情况下,自签名证书可能是合适的。 如果你 do 有一个域名,在很多情况下最好使用 CA 签名的证书。 您可以在此处 的 Let's Encrypt 项目 中了解如何设置免费的可信证书。


先决条件

在开始之前,您应该有一个配置有 sudo 权限的非 root 用户。 您可以按照我们的 Ubuntu 16.04 初始服务器设置来了解如何设置此类用户帐户。

您还需要安装 Nginx Web 服务器。 如果您想在您的服务器上安装整个 LEMP(Linux、Nginx、MySQL、PHP)堆栈,您可以按照我们关于 在 Ubuntu 16.04 上设置 LEMP 的指南进行操作。

如果您只想要 Nginx Web 服务器,您可以按照我们的指南在 在 Ubuntu 16.04 上安装 Nginx。

完成先决条件后,请继续以下操作。

步骤 1:创建 SSL 证书

TLS/SSL 通过使用公共证书和私钥的组合来工作。 SSL 密钥在服务器上是保密的。 它用于加密发送给客户端的内容。 SSL 证书与任何请求内容的人公开共享。 它可用于解密由相关 SSL 密钥签名的内容。

我们可以在一个命令中使用 OpenSSL 创建一个自签名密钥和证书对:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

您将被问到一系列问题。 在我们讨论之前,让我们看一下我们发出的命令中发生了什么:

  • openssl:这是用于创建和管理 OpenSSL 证书、密钥和其他文件的基本命令行工具。
  • req:此子命令指定我们要使用 X.509 证书签名请求 (CSR) 管理。 “X.509”是 SSL 和 TLS 遵循的公钥基础设施标准,用于其密钥和证书管理。 我们想创建一个新的 X.509 证书,所以我们使用这个子命令。
  • -x509:这进一步修改了前面的子命令,告诉实用程序我们要制作自签名证书,而不是像通常发生的那样生成证书签名请求。
  • -nodes:这告诉 OpenSSL 跳过使用密码保护我们的证书的选项。 当服务器启动时,我们需要 Nginx 能够读取文件,而无需用户干预。 密码可以防止这种情况发生,因为我们必须在每次重启后输入它。
  • -days 365:此选项设置证书将被视为有效的时间长度。 我们在这里设置了一年。
  • -newkey rsa:2048:这指定我们要同时生成一个新证书和一个新密钥。 我们没有在上一步中创建签署证书所需的密钥,因此我们需要将其与证书一起创建。 rsa:2048 部分告诉它生成一个 2048 位长的 RSA 密钥。
  • -keyout:这一行告诉 OpenSSL 将我们正在创建的生成的私钥文件放在哪里。
  • -out:这告诉 OpenSSL 在哪里放置我们正在创建的证书。

如上所述,这些选项将创建密钥文件和证书。 我们将被问到一些关于我们服务器的问题,以便将信息正确地嵌入到证书中。

适当地填写提示。 最重要的一行是请求通用名称的行(例如 服务器 FQDN 或您的姓名)。 您需要输入与您的服务器关联的域名,或者更有可能是您的服务器的公共 IP 地址。

整个提示将如下所示:

OutputCountry Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc.
Organizational Unit Name (eg, section) []:Ministry of Water Slides
Common Name (e.g. server FQDN or YOUR name) []:server_IP_address
Email Address []:admin@your_domain.com

您创建的两个文件都将放置在 /etc/ssl 目录的相应子目录中。

当我们使用 OpenSSL 时,我们还应该创建一个强大的 Diffie-Hellman 组,用于与客户端协商 Perfect Forward Secrecy

我们可以通过键入:

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

这可能需要几分钟,但完成后,您将在 /etc/ssl/certs/dhparam.pem 处拥有一个强大的 DH 组,我们可以在我们的配置中使用它。

第 2 步:配置 Nginx 以使用 SSL

我们已经在 /etc/ssl 目录下创建了我们的密钥和证书文件。 现在我们只需要修改我们的 Nginx 配置来利用这些。

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

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

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

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

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

为了正确区分这个文件的用途,我们称它为 self-signed.conf

sudo nano /etc/nginx/snippets/self-signed.conf

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

/etc/nginx/snippets/self-signed.conf

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

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

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

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

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

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

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

上面链接的网站上的建议设置提供了强大的安全性。 有时,这是以更高的客户端兼容性为代价的。 如果您需要支持旧客户端,可以通过单击页面上标有“是的,给我一个适用于旧版/旧版软件的密码套件”的链接访问一个替代列表。 该列表可以代替下面复制的项目。

您使用哪种配置的选择很大程度上取决于您需要支持什么。 它们都将提供极大的安全性。


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

首先,我们将为上游请求添加首选 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;

因为我们使用的是自签名证书,所以不会使用 SSL 装订。 Nginx 将简单地输出一个警告,为我们的自签名证书禁用装订,并继续正常运行。

完成后保存并关闭文件。

调整 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 指令,设置为您服务器的域名,或者更有可能是 IP 地址。 然后,我们将设置重定向到我们将创建的第二个服务器块。 之后,我们将关闭这个短块:

注意: 在我们确认一切正常之前,我们将使用 302 重定向。 之后,我们可以将其更改为永久 301 重定向。


/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 302 https://$server_name$request_uri;
}

    # SSL configuration

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

    . . .

接下来,我们需要在下面直接启动一个新的服务器块来包含剩余的配置。 我们可以取消注释使用端口 443 的两个 listen 指令。 我们可以将 http2 添加到这些行中,以便在此块中启用 HTTP/2。 之后,我们只需要包含我们设置的两个片段文件:

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


/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 302 https://$server_name$request_uri;
}

server {

    # SSL configuration

    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/self-signed.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 http2 default_server;
    listen [::]:443 ssl http2 default_server;

    server_name server_domain_or_IP;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    . . .

完成后保存并关闭文件。

第三步:调整防火墙

如果按照先决条件指南的建议启用了 ufw 防火墙,则需要调整设置以允许 SSL 流量。 幸运的是,Nginx 在安装时使用 ufw 注册了一些配置文件。

我们可以通过键入以下内容查看可用的配置文件:

sudo ufw app list

您应该会看到如下列表:

OutputAvailable applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

您可以通过键入以下内容查看当前设置:

sudo ufw status

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

OutputStatus: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

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

sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'

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

sudo ufw status
OutputStatus: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

第 4 步:启用 Nginx 中的更改

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

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

sudo nginx -t

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

Outputnginx: [warn] "ssl_stapling" ignored, issuer certificate not found
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

注意开头的警告。 如前所述,此特定设置会引发警告,因为我们的自签名证书无法使用 SSL 装订。 这是意料之中的,我们的服务器仍然可以正确加密连接。

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

sudo systemctl restart nginx

第 5 步:测试加密

现在,我们准备好测试我们的 SSL 服务器了。

打开您的网络浏览器并在地址栏中输入 https://,然后是您的服务器的域名或 IP:

https://server_domain_or_IP

由于我们创建的证书未由您的浏览器受信任的证书颁发机构之一签名,您可能会看到一个看起来很吓人的警告,如下所示:

这是预期和正常的。 我们只对我们证书的加密方面感兴趣,而不是对我们主机真实性的第三方验证。 单击“高级”,然后单击提供的链接以继续访问您的主机:

您应该被带到您的网站。 如果您查看浏览器地址栏,您会看到一个带有“x”的锁。 在这种情况下,这仅意味着无法验证证书。 它仍在加密您的连接。

如果你为 Nginx 配置了两个服务器块,自动将 HTTP 内容重定向到 HTTPS,你还可以检查重定向功能是否正确:

http://server_domain_or_IP

如果这导致相同的图标,这意味着您的重定向工作正常。

第 6 步:更改为永久重定向

如果您的重定向工作正常并且您确定只允许加密流量,您应该修改 Nginx 配置以使重定向永久化。

再次打开您的服务器块配置文件:

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

找到 return 302 并将其更改为 return 301

/etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 301 https://$server_name$request_uri;
}

. . .

保存并关闭文件。

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

sudo nginx -t

准备好后,重新启动 Nginx 以使重定向永久化:

sudo systemctl restart nginx

结论

您已将 Nginx 服务器配置为对客户端连接使用强加密。 这将允许您安全地处理请求,并防止外部各方读取您的流量。