介绍
托管 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-tools
和 stunnel4
包:
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+X
、Y
,然后按 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的调试级别,范围从0
到7
。 在此示例中,我们将其设置为可用的最高级别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 部分。 在那里,您将找到描述数据库的 host 和 port 的字段。
这是一个相当简单的配置,它保留了许多 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 数据库 的系列很有用。