在 Linux 上使用 Nginx 和自签名证书实现 HTTPS

CompTIABeginner
立即练习

介绍

在本实验中,你将学习如何通过实现带有自签名证书的 HTTPS 来保护 Linux 上的 Nginx Web 服务器。你将首先安装 Nginx Web 服务器并确保其正常运行,为安全配置奠定基础。在初始设置之后,你将使用 OpenSSL 工具包生成一个自签名 SSL 证书,这是启用加密通信的关键组件。

证书创建完成后,你将继续修改 Nginx 配置,通过安全的 HTTPS 协议来提供 Web 内容。本实验的最后阶段将侧重于验证和测试。你将激活新配置,并使用 curlopenssl 等命令行工具来测试 HTTPS 连接并检查你新创建的自签名证书的详细信息,以确认你的服务器已得到妥善保护。

安装并启动 Nginx Web 服务器

在此步骤中,你将安装 Nginx Web 服务器。Nginx 是一款高性能的 Web 服务器,广泛用于提供 Web 内容。我们将首先安装它,然后验证其是否正常运行。这个运行中的 Nginx 实例将作为我们后续 HTTPS 配置的基础。

首先,更新系统的软件包列表是一个最佳实践,以确保你获取的是最新版本的软件。

在你的终端中执行以下命令:

sudo apt update

你将看到系统从其配置的源获取软件包信息。输出将类似于:

Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
...
Fetched 1,585 kB in 2s (924 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.

现在,你可以继续安装 Nginx。我们将使用 apt install 命令。添加 -y 标志是为了自动确认安装,避免任何交互式提示。

sudo apt install nginx -y

安装过程将下载并设置 Nginx 及其依赖项。完成后,你应该会看到指示 nginx 包已设置的输出。

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  nginx-common nginx-core
...
Setting up nginx-common (1.18.0-6ubuntu14.4) ...
Setting up nginx-core (1.18.0-6ubuntu14.4) ...
Setting up nginx (1.18.0-6ubuntu14.4) ...
Processing triggers for ufw (0.36.1-4ubuntu0.1) ...
Processing triggers for man-db (2.10.2-1) ...

尽管安装过程通常会启动服务,但显式管理它是一个好习惯。我们将使用 systemctl,这是现代 Linux 系统上用于控制服务的标准工具。

使用此命令启动 Nginx 服务:

sudo systemctl start nginx

如果成功执行,此命令将不会产生任何输出。要确认服务正在运行,请检查其状态。

sudo systemctl status nginx

输出将提供有关服务的详细信息。查找 Active: active (running) 行,它确认 Nginx 正在运行。

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2023-10-30 08:30:00 UTC; 5s ago
       Docs: man:nginx(8)
   Main PID: 1234 (nginx)
      Tasks: 2 (limit: 4617)
     Memory: 4.8M
        CPU: 43ms
     CGroup: /system.slice/nginx.service
             ├─1234 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             └─1235 "nginx: worker process"

你现在已成功安装并启动了 Nginx Web 服务器。在下一步中,你将生成一个数字证书,这是启用 HTTPS 的先决条件。

使用 OpenSSL 生成自签名 SSL 证书

在此步骤中,你将创建一个自签名数字证书及其对应的私钥。要启用 HTTPS,Web 服务器需要一个数字证书来向客户端证明其身份,并需要一个私钥来建立安全、加密的连接。我们将使用 openssl 命令行工具,这是一个强大的用于处理 SSL/TLS 的实用程序。

数字证书将公钥与身份(如网站的域名)绑定。通常,证书由受信任的证书颁发机构 (CA) 颁发和签名。然而,出于测试和开发目的,我们可以创建一个自签名证书,它由其自身的创建者签名。虽然浏览器会对此类证书显示安全警告,但它们在此类实验环境中完全可用。

首先,我们在 Nginx 配置文件夹内创建一个专用目录来存储我们的 SSL 证书和密钥。这有助于保持文件组织有序和安全。

sudo mkdir -p /etc/nginx/ssl

现在,我们将使用一个 openssl 命令来生成 2048 位 RSA 私钥和自签名证书,有效期为 365 天。我们将把它们直接放入 /etc/nginx/ssl/ 目录。

以下是命令选项的细分:

  • req -x509: 创建一个自签名证书。
  • -nodes: 防止私钥被密码短语加密。这很重要,这样 Nginx 就可以在没有手动干预的情况下启动。
  • -days 365: 将证书的有效期设置为一年。
  • -newkey rsa:2048: 生成一个新的 2048 位 RSA 私钥。
  • -keyout: 指定私钥的输出文件(/etc/nginx/ssl/nginx.key)。
  • -out: 指定证书的输出文件(/etc/nginx/ssl/nginx.crt)。
  • -subj: 以非交互方式提供证书的主题信息。CN=localhost 是通用名称 (Common Name),它必须与你访问网站时使用的地址匹配。

运行以下命令:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/nginx/ssl/nginx.key \
  -out /etc/nginx/ssl/nginx.crt \
  -subj "/C=US/ST=State/L=City/O=LabOrg/OU=IT/CN=localhost"

运行命令后,你将看到确认密钥生成的输出。

Generating a RSA private key
writing new private key to '/etc/nginx/ssl/nginx.key'
-----

私钥(/etc/nginx/ssl/nginx.key)极其敏感。如果它被泄露,攻击者就可以冒充你的服务器。因此,限制其文件权限至关重要,以便只有 root 用户可以读取它。

sudo chmod 600 /etc/nginx/ssl/nginx.key

此命令将权限设置为仅所有者(root)可读写,其他人没有任何权限。这是一项关键的安全措施。

太棒了!你现在已经创建了一个自签名证书(nginx.crt)和一个安全的私钥(nginx.key)。在下一步中,你将配置 Nginx 来使用这两个文件以启用 HTTPS。

配置 Nginx 通过 HTTPS 提供内容

在此步骤中,你将修改 Nginx 配置以启用 HTTPS。在上一阶段准备好证书和私钥后,现在需要指示 Nginx 使用它们。这涉及到编辑 Nginx 的站点配置文件,使其监听端口 443(HTTPS 的标准端口),并指定证书和密钥文件的路径。

在编辑任何配置文件之前,创建一个备份是一个明智的做法。如果出现问题,这可以让你轻松恢复到原始状态。让我们备份默认的 Nginx 站点配置文件。

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

现在,你将使用 nano 文本编辑器编辑主配置文件。此文件包含服务器块 (server blocks),这些块定义了 Nginx 如何处理传入的请求。

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

nano 编辑器中,你将看到一个为端口 80 上的 HTTP 配置的默认服务器块。滚动到 SSL 配置部分,该部分通常被注释掉了。你需要取消注释此部分,并确保它与下面的配置匹配。此块指示 Nginx 监听端口 443 上的安全连接,并指定在 TLS 握手中使用哪个证书和密钥。

删除现有的被注释掉的 SSL 服务器块,并用以下内容替换它,或者直接取消注释并进行编辑以匹配。

## --- CONTENT TO ADD/UNCOMMENT IN /etc/nginx/sites-available/default ---
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    server_name localhost;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    location / {
        try_files $uri $uri/ =404;
    }
}
## --- END CONTENT ---

以下是这些指令的含义:

  • listen 443 ssl: 告诉 Nginx 监听端口 443 上的传入连接,并使用 SSL/TLS 协议处理它们。
  • server_name localhost: 定义用于处理 localhost 请求的服务器块。
  • ssl_certificate: 指定你的公用证书文件(nginx.crt)的路径。
  • ssl_certificate_key: 指定你的私钥文件(nginx.key)的路径。

添加内容后,保存文件并按 Ctrl+X,然后按 Y,最后按 Enter 退出 nano

在应用更改之前,测试 Nginx 配置是否存在任何语法错误至关重要。这可以防止错误的配置导致你的 Web 服务器宕机。

sudo nginx -t

如果配置正确,你将看到成功消息。

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

如果你看到任何错误,请重新打开配置文件并仔细检查是否有拼写错误或遗漏的分号。

你现在已经成功配置了 Nginx 以通过 HTTPS 提供内容。下一步是通过重新启动服务并测试连接来应用这些更改。

使用 curl 激活并测试 HTTPS 配置

在此步骤中,你将应用新的 Nginx 配置,并确认你的 Web 服务器是否已正确通过 HTTPS 提供内容。虽然你已修改了磁盘上的配置文件,但正在运行的 Nginx 进程仍在使用旧配置。你必须重新启动服务才能使更改生效。

要应用新配置,请使用 systemctl 重新启动 Nginx 服务。

sudo systemctl restart nginx

如果成功,此命令不会产生任何输出。Nginx 现在将监听端口 443,并准备好使用你提供的证书和密钥处理 HTTPS 请求。

现在,让我们测试 HTTPS 端点。我们将使用 curl,这是一个用于通过 URL 传输数据的命令行工具。我们将尝试使用 https:// 协议从服务器获取主页。

当你使用 HTTPS 连接到服务器时,你的客户端(在本例中为 curl)会检查服务器的证书是否由受信任的证书颁发机构 (CA) 签名。由于我们创建了一个自签名证书,它默认不被信任,curl 将拒绝连接,并显示证书验证错误。

为了在测试中解决此问题,我们使用 -k--insecure 标志。此标志告诉 curl 跳过证书验证。这不安全,不应在生产环境中使用,但在实验环境中测试自签名证书是必需的。

运行以下命令来测试你的 HTTPS 服务器:

curl -k https://localhost

如果你的配置正确,curl 将成功连接到服务器,并打印出默认 Nginx 欢迎页面的 HTML 内容。

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

收到此 HTML 输出证实了你的 Nginx 服务器已成功配置并通过加密的 HTTPS 连接提供内容。在最后一步中,你将学习如何检查服务器正在提供的证书。

使用 OpenSSL 检查服务器的 SSL 证书

在最后一步中,你将检查你的 Nginx 服务器向客户端提供的数字证书的详细信息。这是排查 TLS/HTTPS 问题和验证服务器身份的关键技能。你将再次使用 openssl 工具,但这次是作为客户端连接到你自己的服务器并检查它提供的证书。

我们将使用两个 openssl 命令的组合,并通过管道符 (|) 连接它们。

  • openssl s_client -connect localhost:443: 此命令充当通用的 SSL/TLS 客户端,连接到指定的服务器和端口。它将输出服务器的证书以及会话详细信息。
  • openssl x509 -text -noout: 此命令用于解析 X.509 证书并以人类可读的格式显示其内容。

我们将把 s_client 的输出直接通过管道传递给 x509,以便即时解析证书。开头的 echo | 可以防止 s_client 等待用户输入,而 2>/dev/null 则会隐藏连接状态消息。为了清晰起见,我们将输出保存到一个文件中。

执行以下命令以连接到你的服务器,提取证书,解析它,并将详细信息保存到名为 /tmp/server_certificate_details.txt 的文件中。

echo | openssl s_client -connect localhost:443 2> /dev/null | openssl x509 -text -noout > /tmp/server_certificate_details.txt

现在,显示你刚刚创建的文件的内容,以查看证书详细信息。

cat /tmp/server_certificate_details.txt

你将看到证书属性的详细 breakdown。

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = State, L = City, O = LabOrg, OU = IT, CN = localhost
        Validity
            Not Before: Oct 30 09:00:00 2023 GMT
            Not After : Oct 29 09:00:00 2024 GMT
        Subject: C = US, ST = State, L = City, O = LabOrg, OU = IT, CN = localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
                    ...
                Exponent: 65537 (0x10001)
...

花点时间检查输出。注意以下关键字段:

  • Issuer: 签名证书的实体。
  • Subject: 证书颁发给的实体。
  • CN (Common Name): 证书适用的特定域名(localhost)。

由于这是一个自签名证书,IssuerSubject 字段是相同的。这是自签名证书的定义特征。你还可以看到有效期和公钥的详细信息。

恭喜!你已成功设置了一个带有自签名 SSL 证书的 Nginx Web 服务器,将其配置为 HTTPS,测试了连接,并检查了证书详细信息。你现在对保护 TLS/HTTPS 流量所涉及的组件有了基础的理解。

总结

在本实验中,你学习了在 Linux 环境中使用自签名证书在 Nginx Web 服务器上实现 HTTPS 的端到端过程。你首先进行了基础设置,包括使用 apt 包管理器更新系统的包列表并安装 Nginx Web 服务器。实验的核心集中在安全性方面,你使用了 OpenSSL 工具包生成了一个私钥和相应的自签名 SSL 证书,它们是启用加密连接的关键组件。

创建证书后,你继续配置 Nginx 服务器。这包括修改其配置文件以创建一个监听端口 443 以进行 HTTPS 流量的服务器块,并将其指向你的新证书和私钥的路径。为了完成整个过程,你激活了新配置并执行了关键的验证步骤。你使用 curl 命令从命令行测试了 HTTPS 连接,并确认服务器正在安全地响应。最后,你使用 OpenSSL 作为客户端工具检查了服务器的证书,验证了正在提供正确的证书。