如何在Ubuntu 16.04上使用Stunnel加密流量到Redis

介绍

Redis是一个开源键值数据存储,使用内存存储模型和可选的磁盘写入来实现持久性。它具有事务,发布/订阅消息传递模式以及其他功能之间的自动故障转移功能。Redis的客户使用大多数语言编写,并在其网站上提供推荐的客户。

Redis不提供自己的任何加密功能。它的运作假设它已部署到隔离的专用网络,只能由可信方访问。如果您的环境与该假设不匹配,则必须单独将Redis流量包装在加密中。

在本教程中,我们将演示如何使用名为stunnel的安全隧道程序加密Redis流量。Redis客户端和服务器之间的流量将通过专用的SSL加密隧道进行路由。我们将使用两台Ubuntu 16.04服务器进行演示。

准备

当您准备好继续时,请按照下面的步骤操作。

什么是stunnel?

对于基本的加密通信,该stunnel实用程序易于安装和配置。它支持两台机器之间的加密转发。客户端连接到本地端口,并stunnel将其包装加密,然后再将其转发到远程服务器。在服务器端,stunnel侦听已配置的端口并在将流量转发到之前解密流量的本地端口(在我们的示例中为Redis服务器侦听的端口)。

使用stunnel的一些优点是:

  • Ubuntu 包含在其默认存储库中的包
  • Ubuntu包含一个init脚本,可以在启动时自动启动进程
  • 配置简单直观
  • 新隧道用于各种目的。在某些情况下,这可能是一个缺点,但它提供了对访问的精细控制。

一些缺点是:

  • 客户端通过连接到非默认本地端口来连接到远程计算机,这可能在一开始就不直观。
  • 如果连接两台Redis服务器进行复制或群集,则必须在每台计算机上配置两个隧道以进行服务器到服务器通信(一个用于出站,一个用于入站流量)。

考虑到这些特点,让我们开始吧。

安装Redis服务器和客户端软件包

在开始之前,我们应该在一台机器上安装Redis服务器,在另一台机器上安装客户机软件包。如果您已经配置了其中一个或两个,请随时跳过。

注意: Redis服务器指令设置一个测试密钥,稍后将用于测试连接。如果您已经安装了Redis服务器,则可以在测试连接时继续设置此密钥或使用任何其他已知密钥。

安装Redis服务器

我们将使用Chris Lea的Redis服务器PPA来安装最新版本的Redis。使用第三方存储库时请务必小心。在这种情况下,Chris Lea是一个值得信赖的打包工具,他为几个流行的开源项目提供高质量、最新的软件包。

通过输入以下内容,添加PPA并在第一台计算机上安装Redis服务器软件:

sudo apt-add-repository ppa:chris-lea/redis-server
sudo apt-get update
sudo apt-get install redis-server

在此过程中敲击Enter以接受提示。

安装完成后,通过输入以下内容测试您是否可以在本地连接到Redis服务:

redis-cli ping

如果软件已安装并正在运行,您应该看到:

Redis server outputPONG

让我们设置一个我们以后可以使用的密钥:

redis-cli set test 'success'

我们已将测试键设置为该值success。配置完成后,我们将尝试从客户端计算机访问此密钥stunnel

安装Redis客户端

另一台Ubuntu 16.04机器将作为客户端。我们需要的所有软件都可以在redis-tools默认存储库的包中找到:

sudo apt-get update
sudo apt-get install redis-tools

使用远程Redis服务器的默认配置和防火墙处于活动状态时,我们当前无法连接到要测试的远程Redis实例。

在每台计算机上安装并启用stunnel

接下来,您需要在每个服务器和客户端上安装stunnel。Ubuntu包含该实用程序的第四版,在其默认存储库中为stunnel4。如果您不需要在上一节中安装任何内容,请确保在安装之前包含刷新软件包索引的sudo apt-get update命令:

# sudo apt-get update
sudo apt-get install stunnel4

Ubuntu上的服务使用较旧的SysVinit脚本进行启动stunnel,可以由systemd管理。而不是使用本机systemd方法,将服务配置为在启动时启动,您必须修改该/etc/default/stunnel4文件:

sudo nano /etc/default/stunnel4

通过将ENABLED选项设置为“1”,使服务在启动时启动:

. . .
ENABLED=1
. . .

保存并关闭每台服务器上的文件。

接下来,我们将创建一个自签名SSL证书和密钥,用于加密通信。

在Redis服务器上创建自签名SSL证书和密钥

在Redis服务器上,在/etc/stunnel目录中创建自签名SSL证书和密钥。这将用于加密stunnel的两个实例之间的连接。我们将使用该redis-server名称来引用证书和密钥文件:

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/stunnel/redis-server.key -out /etc/stunnel/redis-server.crt

系统将提示您输入和正在创建有关的证书的信息。因为这只会在内部使用,所以这些值并不重要,所以请填写您想要的任何内容。您可以在下面看到一个示例:

Redis server output. . .
-----
Country 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]:DigitalOcean
Organizational Unit Name (eg, section) []:Community
Common Name (e.g. server FQDN or YOUR name) []:redis-server
Email Address []:admin@example.com

输入以下命令限制对生成的.key文件的访问:

sudo chmod 600 /etc/stunnel/redis-server.key

现在我们有了SSL证书和密钥,我们可以创建Redis服务器的stunnel配置文件。

创建Redis服务器stunnel配置文件

在Redis的服务器上的/etc/stunnel目录下打开一个以.conf结尾的文件:

sudo nano /etc/stunnel/redis.conf

在内部,指定在主要部分中写入PID文件的位置。该/run目录旨在存储这些类型的文件,因此我们将使用它:

pid = /run/stunnel-redis.pid

接下来,创建一个空间以配置对Redis服务的访问。你可以随意调用它(我们称之为redis-server)。该部分将此配置与您稍后可能需要在此计算机上配置的任何其他通道分开。

我们需要分别使用certkey指令指定Redis服务器自己的证书和密钥的位置。

我们还将在此处为传入数据定义通道。我们希望通过accept将流量加密到Redis服务器外部IP地址上的默认Redis端口(端口6379)。然后我们希望通过connect将流量传输到本地接口上的默认Redis端口以存储解密的流量。这是Redis服务实际监听的地方:

pid = /run/stunnel-redis.pid
​
[redis-server]
cert = /etc/stunnel/redis-server.crt
key = /etc/stunnel/redis-server.key
accept = redis_servers_public_IP:6379
connect = 127.0.0.1:6379

完成后,保存并关闭文件。

重启stunnel并配置防火墙

现在,在Redis服务器上配置了stunnel,我们可以通过输入以下命令重新启动服务:

sudo systemctl restart stunnel4.service

如果您在检查Redis服务器上侦听连接的服务,您应该看到在公共接口上stunnel的侦听端口6379。您还应该看到Redis正在侦听本地接口上的相同端口:

sudo netstat -plunt
Redis server outputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 public_IP:6379          0.0.0.0:*               LISTEN      4292/stunnel4   
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      2679/redis-server 1
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1720/sshd       
tcp6       0      0 :::22                   :::*                    LISTEN      1720/sshd

虽然stunnel正在侦听公共接口,但防火墙可能还没有配置为允许流量通过。

要允许所有流量到端口6379,请输入:

sudo ufw allow 6379

这将打开对stunnel正在侦听的公共接口上的端口6379的访问。该stunnel端口仅接受加密流量。

将证书分发给客户

每个Redis客户端都需要Redis服务器证书文件的副本。分发.crt文件的最简单方法是简单地在服务器上输出文件的内容,然后将内容复制到连接机器上的相应文件中。

输入以下内容输出Redis服务器上.crt文件的内容:

cat /etc/stunnel/redis-server.crt
Redis server output-----BEGIN CERTIFICATE-----
MIIEGTCCAwGgAwIBAgIJALUdz8P8q8UPMA0GCSqGSIb3DQEBCwUAMIGiMQswCQYD
VQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxFjAUBgNVBAcMDU5ldyBZb3JrIENp
​
. . .
​
Tq7WJk77tk4nPI8iGv1WuK8xTAm5aOncxP16VoMpsDMV+GB1p3nBkMQ/GKF8pPXU
fn6BnDWKmeZqAlBM+MGYAfkbZWdBslrWasCJzs+tehTqL0LLJ6d3Gi9biBPb
-----END CERTIFICATE-----

将显示的证书(包括标记为BEGIN CERTIFICATE和END CERTIFICATE的行)复制到剪贴板。

在客户端计算机上,在/etc/stunnel目录中打开具有相同名称的文件:

sudo nano /etc/stunnel/redis-server.crt

粘贴从Redis服务器复制的内容。完成后保存并关闭文件。

创建Redis客户端stunnel配置文件

既然客户端有服务器证书的副本,我们可以配置配置的客户端stunnel

在客户端计算机上的/etc/stunnel目录打开以.conf结尾的文件。我们将再次调用该redis.conf文件:

sudo nano /etc/stunnel/redis.conf

在内部,指定一个PID文件,服务将再次存储其进程ID:

pid = /run/stunnel-redis.pid

接下来,添加一个部分以配置出站数据的通道。您可以根据自己的喜好命名(我们称之为redis-client)。该部分将此配置与您稍后可能需要在此计算机上配置的任何其他隧道分开。

我们需要使用该client指令将此部分明确标记为客户端配置。设置accept指令以侦听本地接口上未使用的端口以处理来自本地Redis客户端的连接(在此示例中我们将使用端口8000)。将connect指令设置为Redis服务器的公共IP地址和我们打开的端口。

然后使用CAfile指向Redis服务器证书的副本。我们还必须设置verify为4,这样stunnel只检查证书而不考虑证书链(因为我们自签了证书):

pid = /run/stunnel-redis.pid
​
[redis-client]
client = yes
accept = 127.0.0.1:8000
connect = remote_server_IP_address:6379
CAfile = /etc/stunnel/redis-server.crt
verify = 4

完成后保存并关闭文件。

重新启动客户端服务并测试连接

在客户端上重新启动stunnel服务以实现更改:

sudo systemctl restart stunnel4.service

检查客户端上的隧道是否已正确设置:

sudo netstat -plunt
Redis client outputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      3809/stunnel4   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1714/sshd       
tcp6       0      0 :::22                   :::*                    LISTEN      1714/sshd

如您所见,stunnel正在侦听本地端口8000以获取连接。

现在,您应该能够通过将客户端指向本地接口上的端口8000来连接到远程Redis实例:

redis-cli -p 8000 ping
Redis client outputPONG

查询我们在本教程开头设置的测试密钥:

redis-cli -p 8000 get test
Redis client output"success"

这证实我们能够成功访问远程数据库。

要确认我们无法在不使用通道的情况下与远程Redis服务器通信,我们可以尝试直接连接到远程端口:

redis-cli -h redis_server_public_IP -p 6379 ping
Redis client outputError: Connection reset by peer

如您所见,只有通过通道正确加密后,才能在远程Redis端口上接收流量。

扩展上述多客户端和服务器到服务器通信的示例

我们上面概述的示例使用了单个Redis服务器和单个客户端的简单示例。但是,这些相同的方法可以应用于更复杂的交互。

扩展此示例以处理多个客户端非常简单。您需要执行上面列出的以下操作。

  • 在新客户端上安装Redis客户端软件和stunnel软件包
  • 使stunnel软件在开机时启动
  • 将服务器的证书文件复制到该/etc/stunnel目录
  • stunnel客户端配置文件复制到新客户端计算机
  • 重启stunnel服务

要设置安全的服务器到服务器通信(例如,用于复制或集群),您需要设置两个并行通道:

  • 在新服务器上,安装Redis服务器软件包 stunnel
  • 使stunnel软件在开机时启动
  • 为新的Redis服务器生成新的证书和密钥文件(使用文件的唯一名称)
  • /etc/stunnel目录中的每个证书文件从一个服务器复制到另一个服务器中
  • 在每台服务器(包括现有服务器)上编辑或创建配置stunnel文件,使其包含:
    • 将外部端口映射到本地Redis的服务器部分
    • 客户端部分将本地端口映射到远程服务器的公开端口
  • 在新的Redis服务器上打开防火墙中的外部端口
  • 通过调整Redis配置文件,将每个Redis实例配置为连接到本地映射的端口以访问远程服务器(所需的指令取决于服务器的关系。有关更多详细信息,请参阅Redis文档)。

两个服务器的stunnel配置文件如下所示:

用于服务器到服务器通信的stunnel配置文件

pid = /run/stunnel-redis.pid
​
[redis-server]
cert = /etc/stunnel/this_servers_certificate.crt
key = /etc/stunnel/this_servers_key.key
accept = this_servers_public_IP:6379
connect = 127.0.0.1:6379
​
[redis-client]
client = yes
accept = 127.0.0.1:arbitrary_local_port
connect = remote_servers_public_IP:6379
CAfile = /etc/stunnel/remote_servers_certificate.crt
verify = 4

如有必要,可以在每台计算机上配置多个客户端部分,以将本地端口映射到远程服务器。在这些情况下,请确保为每个远程服务器选择一个不同的未使用的本地端口和accept指令。

结论

Redis是一个功能强大且灵活的工具,对许多部署都非常有用。但是,在不安全的环境中运行Redis是一项巨大的挑战,容易使您的服务器和数据受到攻击或盗窃。如果您没有仅由受信任方填充的隔离网络,则必须通过其他方式保护流量。本教程中概述的方法只是确保Redis各方之间通信的一种方法。还有其他选择比如使用spiped进行隧道连接或设置VPN。

想要了解更多关于的开源信息教程,请前往腾讯云+社区学习更多知识。

参考文献:《How To Encrypt Traffic to Redis with Stunnel on Ubuntu 16.04》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Porschev[钟慰]的专栏

Windows Server 2008 R2 下配置证书服务器和HTTPS方式访问网站

配置环境Windows版本:Windows Server 2008 R2 Enterprise                      Service Pa...

42060
来自专栏IT开发技术与工作效率

★Outlook邮件模板

29620
来自专栏云知识学习

Tomcat开启SSL 8443端口的方法

TOMCAT_HOME:/usr/local/tomcat7,安装方法参考:windows和linux 下将tomcat注册为服务

661110
来自专栏游戏杂谈

Linux下的Nginx安装(开机自启动)

pcre:8.12     下载地址: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/

66620
来自专栏康怀帅的专栏

PHP curl 详解

本文详细记录了 PHP 使用 curl 遇到的问题。 官方文档:http://php.net/manual/zh/book.curl.php 设置网址 curl...

34970
来自专栏云计算教程系列

给你CVM服务器加把锁,如何使用SSH密钥

SSH或安全shell是用于管理服务器和与服务器通信的加密协议。使用Ubuntu服务器时,您可能会将大部分时间花在通过SSH连接到服务器中。

19840
来自专栏云计算教程系列

如何在Debian 9上安装和配置Nextcloud

Nextcloud是ownCloud的一个分支,它是一个文件共享服务器,允许您将个人内容(如文档和图片)存储在集中位置,就像Dropbox一样。与Nextclo...

1.9K30
来自专栏FreeBuf

Redis未授权访问漏洞的重现与利用

前言: 最近配置openvas的时候安装了redis,听说曾经曝出过一个未授权访问漏洞,便找了一下相关资料想自己动手复现一下漏洞的利用过程,当然所有的攻击性操作...

318100
来自专栏小白安全

SQL注入 上传绕过安全狗

一,绕过安全狗上传可执行脚本 附上php上传脚本源码,此源码未对上传文件类型做校验 <?php         move...

63670
来自专栏云计算教程系列

如何使用Spiped在Ubuntu 16.04上加密到Redis的流量

Redis是一个开源键值数据存储,使用内存存储模型和可选的磁盘写入来实现持久性。它具有事务,发布/订阅消息传递模式以及其他功能之间的自动故障转移功能。Redis...

37900

扫码关注云+社区

领取腾讯云代金券