如何使用Stunnel和redis-cli通过TLS连接到托管Redis实例

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

介绍

托管 Redis 实例可以提供高可用性和自动更新等优势。 但是,每当您连接到远程数据库服务器时,都会冒着恶意行为者 嗅探 您发送给它的敏感信息的风险。

Redis 命令行界面 redis-cli 本身不支持通过 TLS 的连接,这是一种允许通过网络进行安全通信的加密协议。 这意味着如果没有进一步的配置,redis-cli 不是连接远程 Redis 服务器的安全方式。 与托管 Redis 实例建立安全连接的一种方法是创建使用 TLS 协议的 隧道

Stunnel 是一个开源代理,用于创建安全隧道,允许您通过 TLS 与其他机器通信。 在本指南中,我们将介绍如何安装和配置 stunnel,以便您可以使用 redis-cli 通过 TLS 连接到托管 Redis 实例。

先决条件

要完成本指南,您需要:

  • 访问 Ubuntu 18.04 服务器。 此服务器应具有具有管理权限的非 root 用户和配置为 ufw 的防火墙。 要进行此设置,请按照我们的 Ubuntu 18.04 初始服务器设置指南进行操作。
  • 托管 Redis 数据库实例。 本教程中概述的步骤在 DigitalOcean 托管 Redis 数据库上进行了测试,尽管它们通常适用于来自任何云提供商的托管数据库。 要配置 DigitalOcean Managed Redis 数据库,请遵循我们的 Managed Redis 产品文档

第 1 步 — 安装 Stunnel 和 redis-cli

安装 Redis 服务器时,通常会附带 redis-cli。 但是,您可以通过从默认 Ubuntu 存储库安装 redis-tools 软件包,在没有 Redis 服务器的情况下安装 redis-cli。 您还可以通过下载 stunnel4 包从默认的 Ubuntu 存储库安装 stunnel。

首先,如果您最近没有这样做,请更新服务器的包索引:

sudo apt update

然后使用 APT 安装 redis-toolsstunnel4 包:

sudo apt install redis-tools stunnel4

出现提示时,按 ENTER 确认您要安装这些软件包。

您可以通过运行以下命令来检查 stunnel 是否安装正确以及其 systemd 服务是否正常工作:

sudo systemctl status stunnel4
Output● stunnel4.service - LSB: Start or stop stunnel 4.x (TLS tunnel for network daemons)
   Loaded: loaded (/etc/init.d/stunnel4; generated)
   Active: active (exited) since Thu 2019-09-12 14:34:05 UTC; 8s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 0 (limit: 2362)
   CGroup: /system.slice/stunnel4.service

Sep 12 14:34:05 stunnel systemd[1]: Starting LSB: Start or stop stunnel 4.x (TLS tunnel for network daemons)...
Sep 12 14:34:05 stunnel stunnel4[2034]: TLS tunnels disabled, see /etc/default/stunnel4
Sep 12 14:34:05 stunnel systemd[1]: Started LSB: Start or stop stunnel 4.x (TLS tunnel for network daemons).

在这里,您可以看到 stunnel 服务处于活动状态,尽管该进程立即退出。 这告诉我们 stunnel 正在运行,但它实际上无法执行任何操作,因为我们尚未对其进行配置。

第 2 步 — 配置 Stunnel

现代 Linux 系统依赖 systemd 来初始化和管理服务和守护进程。 但是,stunnel 使用 SysV 样式的 init 脚本来启动,该脚本基于旧的 UNIX System V 初始化系统。 您需要修改 /etc/default/stunnel4 文件以启用此初始化脚本。

使用您喜欢的文本编辑器打开此文件。 在这里,我们将使用 nano

sudo nano /etc/default/stunnel4

找到文件顶部附近的 ENABLED 选项。 默认情况下它将设置为 0,但将其更改为 1 以启用 stunnel 在启动时启动:

/etc/default/stunnel4

# /etc/default/stunnel
# Julien LEMOINE <speedblue@debian.org>
# September 2003

# Change to one to enable stunnel automatic startup
ENABLED=1
. . .

保存并关闭文件。 如果您使用 nano 编辑文件,请按 CTRL+XY,然后按 ENTER

接下来,您需要为 stunnel 创建一个配置文件,该文件将告诉程序它需要将流量路由到哪里。

/etc/stunnel 目录下打开一个名为 stunnel.conf 的新文件:

sudo nano /etc/stunnel/stunnel.conf

将以下内容添加到该文件中:

/etc/stunnel/stunnel.conf

fips = no
setuid = nobody
setgid = nogroup
pid = /home/sammy/pids/stunnel.pid
debug = 7
delay = yes
[redis-cli]
  client = yes
  accept = 127.0.0.1:8000
  connect = managed_redis_hostname_or_ip:managed_redis_port

文件中的前五行是 全局选项 ,这意味着它们将应用于您包含在此文件中的每个服务:

  • fips:启用或禁用 stunnel 的 FIPS 140-2 模式。 在此模式下,stunnel 将验证连接是否符合 联邦信息处理标准 。 将此设置为 no 将禁用此功能。 请注意,禁用它并不会降低安全性,但保持启用它(默认情况下)将需要一些额外的配置。
  • setuid:定义运行 stunnel 的 Unix 用户 ID。 默认情况下,stunnel 进程由 root 用户拥有。 但是,stunnel 文档建议 在隧道启动后放弃管理权限,因为不这样做会带来安全风险。 将 setuid 参数设置为 nobody 将导致 nobody(非特权用户)在隧道建立后接管 stunnel 进程。
  • setgid:定义 stunnel 运行的 Unix 组 ID。 与 setuid 一样,此配置指定一个没有任何特殊权限的组 - nogroup - 以避免任何潜在的安全问题。
  • pid:定义 stunnel 将在其中创建 .pid 文件的文件位置,该文件类型包含进程的 PID.pid 文件通常被其他程序用来查找正在运行的进程的 PID。 默认情况下,stunnel 在 /var/run/stunnel4/ 目录下创建一个 .pid 文件,但是由于 nobody 用户没有访问该目录的权限,它会阻止隧道启动正确。 相反,这一行指定了一个名为 stunnel.pid 的文件,该文件保存在 Ubuntu 用户主目录中名为 pids 的目录中。 我们将很快创建这个目录和 stunnel.pid 文件。 添加此行时,请务必将 sammy 更改为您的 Ubuntu 系统用户的名称。
  • debug:设置stunnel的调试级别,范围从07。 在此示例中,我们将其设置为可用的最高级别 7,因为如果 stunnel 遇到任何问题,它将提供最详细的信息。 您可以将其设置为您喜欢的任何级别,但请注意默认设置为 5
  • delay:当设置为 yes 时,此选项会导致 stunnel 延迟 DNS 查找 connect 选项中列出的地址。 它还将防止 stunnel 缓存 IP 地址。 即使托管 Redis 实例离线,此设置也有助于保持隧道打开,这在扩展集群时可能发生。

其余行是 服务级别选项 ,仅适用于我们将为 redis-cli 创建的隧道:

  • [redis-cli]:这是一个 服务名称 并指定以下行表示客户端程序的单个服务配置。 您可以在 stunnel 配置文件中拥有多个服务,但每个服务都必须与现有的客户端应用程序相关联,并且您不能为同一个应用程序拥有两个服务。
  • client:将此设置为 yes 告诉 stunnel 在客户端模式下运行,这意味着 stunnel 将连接到 TLS 服务器(托管 Redis 实例),而不是充当 TLS 服务器。
  • accept:定义 stunnel 将接受来自客户端的连接的主机和端口。 在这里,我们指定 IP 地址 127.0.0.1,这是一个 IPv4 环回地址,用于表示 localhost 和端口 8000。 这意味着 stunnel 将在端口 8000 上侦听源自 Ubuntu 服务器的连接并对其进行加密。 请注意,您可以将端口设置为您喜欢的任何端口号,只要它尚未在使用中即可。
  • connect:定义 stunnel 将建立连接的远程地址和端口。 请务必更改此参数以与托管数据库的端口和主机名或 IP 地址保持一致。

注意: 您应该在 connect 指令中指定的主机名或 IP 地址和端口将特定于您自己托管的 Redis 数据库。 这些通常可以在您配置 Redis 实例的云提供商的数据库管理用户界面中找到。

如果您使用的是 DigitalOcean 托管 Redis 数据库,您可以通过转到 控制面板 并单击左侧边栏菜单中的 数据库 来找到此信息。 然后,单击要连接的 Redis 实例的名称并向下滚动到 Connection Details 部分。 在那里,您将找到描述数据库的 hostport 的字段。


这是一个相当简单的配置,它保留了许多 stunnel 的默认设置。 该程序有许多选项可供您创建适合您特定需求的隧道。 更多详情请参见官方文档

添加此内容后,保存并关闭文件。

接下来,确保您位于 Ubuntu 用户的主目录中:

cd

然后创建 pids 目录,该目录将保存 stunnel.pid 文件:

mkdir pids

stunnel进程会自动创建stunnel.pid文件,不需要你自己创建文件。 但是,您确实需要将 pids 目录的所有权更改为 nobody 用户和 nogroup 组:

sudo chown -R nobody:nogroup pids/

然后,重启 stunnel4 服务,让 stunnel 读取新的配置文件:

sudo systemctl restart stunnel4

之后,您可以通过调用 netstat(用于显示网络连接的命令行实用程序)来测试 stunnel 是否成功创建隧道。 运行以下命令,将 netstat 输出通过管道传输到 grep 命令,该命令依次搜索 stunnel 的每个实例:

sudo netstat -plunt | grep stunnel
[secondary_label Output] 
tcp        0      0 127.0.0.1:8000         0.0.0.0:*               LISTEN      17868/stunnel 

此输出显示 stunnel 正在侦听本地端口 8000 上的连接。

您还可以使用显示所有当前运行进程的程序 ps 确认 nobody 用户已获得 stunnel 进程的所有权:

ps aux | grep stunnel
[secondary_label Output] 
nobody   15674  0.0  0.1 121912  3180 ?        Ssl  19:28   0:00 /usr/bin/stunnel4 /etc/stunnel/stunnel.conf
. . .

在这里,您可以看到 nobody 确实接管了 stunnel 进程。

Stunnel 现在已完全配置并在您的系统上运行。 您已准备好连接到托管 Redis 实例并测试隧道是否按预期工作。

第 3 步 — 通过 TLS 连接到您的托管数据库

现在您已经在服务器上安装了 redis-cli 并配置了 stunnel,您可以通过 TLS 连接到托管数据库。

根据在步骤 2 中创建的配置文件中定义的设置,您将使用以下命令连接到托管数据库:

redis-cli -h localhost -p 8000

该命令包含 -h 标志,它告诉 redis-cli 下一个参数将是要连接的主机。 在这种情况下,它是 localhost,因为我们正在连接到在服务器上本地创建的隧道。 之后是 -p 标志,它位于我们要连接的本地隧道的端口之前,在本例中是端口 8000

运行该命令后,您将连接到托管的 Redis 服务器。 您的提示将更改以反映您已连接并处于 redis-cli 的交互模式:


注意: 通常,托管数据库配置为要求用户在连接时使用密码进行身份验证。 如果您的托管 Redis 实例需要密码,您可以在 redis-cli 命令中包含 -a 标志,然后是您的密码:

redis-cli -h localhost -p 8000 -a password

或者,您可以通过在建立连接后运行 auth 命令和密码来进行身份验证:

auth password

如果您使用的是 DigitalOcean 托管数据库,您可以在找到其主机名和端口的相同位置找到您的 Redis 实例的密码。 在您的 控制面板 中,单击左侧边栏菜单中的 数据库 。 然后,单击您已连接到的 Redis 实例的名称。 向下滚动到 Connection Details 部分,您会在那里找到标有 password 的字段。 单击 show 按钮以显示密码,然后将其复制并粘贴到这些命令中的任何一个中 - 替换 password - 以进行身份验证。


您可以通过在 Redis 的交互模式下运行 ping 命令来测试隧道是否按预期工作:

ping

如果连接是活动的,它将返回 PONG

[secondary_label Output] 
PONG

但是,如果 stunnel 没有正确地将流量从您的服务器传输到您的 Redis 实例,您可能会在与 Redis 断开连接之前看到如下错误消息:

[secondary_label Output] 
Error: Server closed the connection

如果您收到此错误或类似错误,请仔细检查您是否在 stunnel.conf 文件中正确输入了 Redis 实例的主机名和端口。 同样,请确保您在 redis-cli 命令中输入了正确的端口号。

当托管 Redis 实例重置其打开的连接时,您也可能会收到此错误,当您扩展集群的配置时可能会发生这种情况。 在这种情况下,您可能不会与 Redis 断开连接,尽管您需要重新进行身份验证。

确认隧道正常工作后,请继续断开与 Redis 实例的连接:

exit

如果您更改了 stunnel 的配置,则需要重新加载或重新启动 stunnel4 服务,以便 stunnel 注意到更改:

sudo systemctl reload stunnel4

如果您在未来的任何时候想要关闭 TLS 隧道,您也可以使用 systemctl 来关闭:

sudo systemctl stop stunnel4

隧道关闭后,您可以通过再次启动服务来重新打开隧道:

sudo systemctl start stunnel4

现在您已经成功配置了 stunnel,您可以开始使用 redis-cli 将数据添加到托管 Redis 实例。

结论

Stunnel 是一个方便的工具,用于创建 TLS 隧道并建立与远程服务器的安全连接。 这在机器之间的信息安全传输至关重要的情况下尤其有用,例如远程数据库。

从这里开始,您可以开始探索 Redis 并将其与您的下一个应用程序集成。 如果您不熟悉 Redis,您可能会发现我们关于 如何管理 Redis 数据库 的系列很有用。