dot 快速的未来正在您的城市举办的活动中到来。

加入我们参加 Redis 发布会

使用 Stunnel 保护 Redis

使用 Stunnel 保护 Redis 客户端和服务器

如果您想保护对 Redis 的访问权限该怎么办?普通密码身份验证(即 AUTH 命令)只能帮助您到此为止,在某些情况下,您需要更强大的东西。您可以采取多种方式来实现这一点,例如使用防火墙保护您的 Redis 或使用 spiped,但(在 Heartbleed 之后)SSL 仍然是我最喜欢的选择之一。以下文章解释了如何使用 stunnel 在 Redis 客户端和服务器之间建立安全的(即经过身份验证和加密的)通信通道。当然,这是 DIY 硬核方法,因此,如果您想在没有繁重操作的情况下使用 Redis 和 SSL,请查看我们的计划和 原生支持 SSL 的 Redis 客户端

— Itamar

以下帖子最初发表于 Benjamin Cane 的博客 上,时间为 2014 年 2 月 18 日,网址为 通过 Stunnel 将 Redis 流量发送到 SSL 隧道

最近,如果您一直关注科技甚至主流媒体,您可能会看到一些有关数据泄露的报道。有时,这些数据泄露会让攻击者收集未加密的密码或信用卡号码。在过去,此类攻击仍然会发生,但次数不如今天多,发生时也会保密。随着越来越多的基于互联网的服务成为人们生活的一部分,针对攻击者的目标也越来越多,这些攻击者试图获取敏感数据。

这些攻击者在获取数据的途径上往往非常狡猾,很多时候他们通过访问数据库来做到这一点,但另一个常见的获取和窃取数据的地方是通过未加密的网络流量。许多常用的服务要么不支持 SSL 加密,要么很少使用该选项。Redis 分布式内存缓存是一个较新的服务,目前不支持 SSL 连接。我最近在我的一个副项目中一直在使用 Redis,但我发现自己一直受到缺乏 SSL 加密的限制。

Redis 安全

Redis 旨在在可信的私有网络中使用,不支持 SSL 加密连接。虽然这对许多实现来说是可以的,但这并不适合基于云的实现。虽然一些云提供商提供私有网络,但并非所有提供商都提供。因此,如果您想在一台服务器上运行 Redis 主服务器,并在另一台服务器上运行您的应用程序,别无选择,只能让该连接保持未加密状态。将这些敏感流量发送到云提供商网络甚至是一般互联网,没有任何保护措施可以防止有人使用网络嗅探器。

在本文中,我将向您展示如何使用 stunnel 保护您的 Redis 连接。本文应该处理保护连接的 SSL 部分,但您还应该遵循 Redis 安全中的其他建议。

什么是 stunnel

stunnel 应用程序是一个 SSL 加密包装器,它可以通过 SSL 加密隧道将未加密的流量(例如 redis)隧道到另一台服务器。虽然 stunnel 添加了 SSL 加密,但它不能保证流量永远不会以未加密的方式被捕获。如果攻击者能够破坏服务器或客户端服务器,他们就可以在流量发送到 stunnel 时捕获未加密的本地流量。

使用 stunnel 将 Redis 流量包装在 SSL 中

在今天的文章中,我们将使用 stunnel 对来自 **客户端** 主机到 **服务器** 主机的流量进行加密。我们将在 **客户端** 和 **服务器** 主机上安装 stunnel,并建立一个隧道,将 **客户端** 上的 localhost:6379 重定向到运行在 **服务器** 上的 Redis 实例。

设置服务器主机

我们将首先安装 redis,然后设置 stunnel 以将来自外部来源的连接转发到本地 Redis 实例。

安装 redis-server 软件包

要安装 redis,我们将使用 apt-get

root@server:~# apt-get install redis-server

配置 redis 服务

安装后,我们只需要对 redis 配置进行一项更改。为了提高安全性,我们将启用 requirepass,这要求所有客户端在能够从 Redis 实例提取或放入数据之前进行身份验证。

root@server:~# vi /etc/redis/redis.conf

查找

# requirepass foobared

替换为

requirepass <yourpass>

示例

requirepass foobared

重启 redis 服务

安装后,redis-server 会自动启动,为了使我们的配置更改生效,我们需要重启实例。

root@server:~# /etc/init.d/redis-server restart

安装 stunnel

现在,redis 已安装并运行,我们将安装 stunnel。为了方便起见,我们也将使用 apt-get 安装 stunnel。

root@server:~# apt-get install stunnel4

在启动时启动 stunnel

与 redis 不同,stunnel 在启动时不会自动启动。要在启动时启动 stunnel,我们需要编辑 /etc/default/stunnel 文件。

root@server:~# vi /etc/default/stunnel4

查找

ENABLED=0

替换为

ENABLED=1

创建自签名证书

与任何其他 SSL 协议一样,stunnel 需要一个证书才能用于客户端到服务器的通信。虽然您可以从 Verisign 等证书颁发机构获取签名的证书,但由于我们只在内部使用它,因此可以创建自签名证书。

生成密钥

首先,我们将创建一个私钥,我使用 openssl 来创建一个 4096 位 RSA 密钥。在我的示例中,我使用 4096 位密钥,因为它 比 1024 位或 2048 位密钥更安全

root@server:~# openssl genrsa -out /etc/stunnel/key.pem 4096
创建证书

现在我们已经生成了一个密钥,我们将创建一个证书。在生成证书时,我们会问一些问题;提供的答案用于证明证书的有效性。-days 标志指定此证书的有效期,如果需要,可以修改它,但 5 年应该足够了。

root@server:~# openssl req -new -x509 -key /etc/stunnel/key.pem -out /etc/stunnel/cert.pem -days 1826

由于这实际上只是用于内部通信,因此没有对这些问题的正确或错误答案,但以下示例可以作为回答证书问题的指南。

示例

root@server:~# openssl req -new -x509 -key /etc/stunnel/key.pem -out /etc/stunnel/cert.pem -days 1826
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Arizona
Locality Name (eg, city) []:Phoenix
Organization Name (eg, company) [Internet Widgits Pty Ltd]:BenCane.com
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:bencane.com
Email Address []:testing@example.com
将两个文件合并

我们将密钥和证书合并到一个文件中,供 stunnel 使用。我们还将更改文件权限,以限制谁有权读取这些密钥文件。

root@server:~# cat /etc/stunnel/key.pem /etc/stunnel/cert.pem > /etc/stunnel/private.pem
root@server:~# chmod 640 /etc/stunnel/key.pem /etc/stunnel/cert.pem /etc/stunnel/private.pem

配置 stunnel

默认情况下,stunnel 读取 /etc/stunnel/ 中的所有 *.conf 文件。我们将创建一个名为 redis-server.conf 的文件,并将我们的配置放在其中。

root@server:~# vi /etc/stunnel/redis-server.conf

添加

cert = /etc/stunnel/private.pem
pid = /var/run/stunnel.pid
[redis]
accept = <yourexternalip>:6379
connect = 127.0.0.1:6379

示例

cert = /etc/stunnel/private.pem
pid = /var/run/stunnel.pid
[redis]
accept = 10.0.3.65:6379
connect = 127.0.0.1:6379

默认情况下,redis 监听 localhost IP 127.0.0.1 上的端口 6379。我们的配置让 stunnel accept 外部 IP 上的连接,并将连接转发到监听 127.0.0.1:6379 的 redis 实例。

启动 stunnel

配置完文件后,我们将启动 stunnel。

root@server:/etc/stunnel# /etc/init.d/stunnel4 start

设置客户端主机

此时,**服务器** 主机已设置并准备就绪,我们需要设置 **客户端** 服务器以使用 stunnel 启动 SSL 隧道。

安装 redis-server

在这个示例中,我们也将安装 **客户端** 上的 redis-server;虽然此步骤只是为了安装 redis-cli 工具。如果您正在将此设置用于在 **客户端** 主机上运行的应用程序,则很可能不需要安装 redis-server;因此请记住,这部分是可选的。

root@client:~# apt-get install redis-server
不要在启动时启动 redis-server

默认情况下,redis 在启动时启动,但是我们不希望 redis 在 **客户端** 主机上运行。要禁用 redis 在启动时启动,我们可以使用 update-rc.d 命令。

root@client:~# /etc/init.d/redis-server stop
root@client:~# update-rc.d redis-server disable

安装 stunnel

在 **客户端** 上安装 stunnel 与在 **服务器** 上安装类似,只是配置略有不同。

root@client:~# apt-get install stunnel4

在启动时启动 stunnel

要让 stunnel 在启动时启动,我们需要编辑 /etc/default/stunnel4 文件。

root@client:~# vi /etc/default/stunnel4

查找

ENABLED=0

替换为

ENABLED=1

将证书文件从服务器复制到客户端

为了建立 SSL 连接,我们需要在 **服务器** 主机上生成的 private.pem 文件。您始终应该对该密钥执行良好的证书管理操作,如果它落入坏人之手,攻击者就可以解密以前捕获的任何 SSL 流量。

root@client:~# scp root@10.0.3.65:/etc/stunnel/private.pem /etc/stunnel/
root@client:~# chmod 640 /etc/stunnel/private.pem

配置 stunnel 客户端

stunnel 客户端配置与服务器配置非常类似,为了指定此 stunnel 实例是客户端,我们将在配置中添加 client = yes

root@client:~# vi /etc/stunnel/redis-client.conf

添加

cert = /etc/stunnel/private.pem
client = yes
pid = /var/run/stunnel.pid
[redis]
accept = 127.0.0.1:6379
connect = <serverip>:6379

示例

cert = /etc/stunnel/private.pem
client = yes
pid = /var/run/stunnel.pid
[redis]
accept = 127.0.0.1:6379
connect = 10.0.3.65:6379

在客户端实例上,acceptconnect 设置与服务器配置相反。这告诉 stunnel 在本地端口 6379 上监听,并将连接转发到端口 6379 的**服务器**主机 IP。

启动 stunnel

配置完成后,我们可以启动 stunnel 服务。

root@client:~# /etc/init.d/stunnel4 start

测试连接

现在,**服务器**和**客户端**主机都已安装 stunnel 并建立了 SSL 隧道,我们可以使用 redis-cli 命令连接到**客户端**的 localhost 来测试此连接。

root@client:~# redis-cli -h localhost 
redis localhost:6379> auth foobared
OK

此配置的工作方式是,当**客户端**主机上的客户端连接到本地端口 6379 时,它将通过 stunnel 与**服务器**主机建立的 SSL 隧道转发,并重定向到运行在**服务器**上的 redis 实例。要设置一个应用程序来调用此实例,您只需在**客户端**主机上安装该应用程序,并让它像我的示例所示的那样连接到 localhost 上的 redis。

此相同的设置也可以用于设置 Redis 中的主从复制,但是从实例需要监听除默认 6379 以外的端口。

Benjamin Cane,又名 @madflogo,是 CloudRoutes 的创始人,也是金融服务行业的高可用性和持续可用性系统解决方案架构师。他从事 Linux 和 Unix 系统管理已有 10 多年。你可能会发现他在撰写和分享关于 Linux、Unix、Python、DevOps 以及其他各种系统管理员相关内容的故事。

访问 Redis 了解更多关于 Redis 技术的信息。