Redis是一个开源键值数据存储,使用内存存储模型和可选的磁盘写入来实现持久性。它具有事务,发布/订阅消息传递模式以及其他功能之间的自动故障转移功能。Redis的客户使用大多数语言编写,并在其网站上提供推荐的客户。
Redis不提供自己的任何加密功能。它的运作假设它已部署到隔离的专用网络,只能由可信方访问。如果您的环境与该假设不匹配,则必须单独将Redis流量包装在加密中。
在本教程中,我们将演示如何使用名为stunnel
的安全隧道程序加密Redis流量。Redis客户端和服务器之间的流量将通过专用的SSL加密隧道进行路由。我们将使用两台Ubuntu 16.04服务器进行演示。
sudo
命令的非root账号的Ubuntu 16.04服务器。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。当您准备好继续时,请按照下面的步骤操作。
对于基本的加密通信,该stunnel
实用程序易于安装和配置。它支持两台机器之间的加密转发。客户端连接到本地端口,并stunnel
将其包装加密,然后再将其转发到远程服务器。在服务器端,stunnel
侦听已配置的端口并在将流量转发到之前解密流量的本地端口(在我们的示例中为Redis服务器侦听的端口)。
使用stunnel
的一些优点是:
一些缺点是:
考虑到这些特点,让我们开始吧。
在开始之前,我们应该在一台机器上安装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
。
另一台Ubuntu 16.04机器将作为客户端。我们需要的所有软件都可以在redis-tools
默认存储库的包中找到:
sudo apt-get update
sudo apt-get install redis-tools
使用远程Redis服务器的默认配置和防火墙处于活动状态时,我们当前无法连接到要测试的远程Redis实例。
接下来,您需要在每个服务器和客户端上安装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服务器上,在/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的服务器上的/etc/stunnel
目录下打开一个以.conf
结尾的文件:
sudo nano /etc/stunnel/redis.conf
在内部,指定在主要部分中写入PID文件的位置。该/run
目录旨在存储这些类型的文件,因此我们将使用它:
pid = /run/stunnel-redis.pid
接下来,创建一个空间以配置对Redis服务的访问。你可以随意调用它(我们称之为redis-server
)。该部分将此配置与您稍后可能需要在此计算机上配置的任何其他通道分开。
我们需要分别使用cert
和key
指令指定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
完成后,保存并关闭文件。
现在,在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服务器复制的内容。完成后保存并关闭文件。
既然客户端有服务器证书的副本,我们可以配置配置的客户端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服务器和单个客户端的简单示例。但是,这些相同的方法可以应用于更复杂的交互。
扩展此示例以处理多个客户端非常简单。您需要执行上面列出的以下操作。
stunnel
软件包stunnel
软件在开机时启动/etc/stunnel
目录stunnel
客户端配置文件复制到新客户端计算机stunnel
服务要设置安全的服务器到服务器通信(例如,用于复制或集群),您需要设置两个并行通道:
stunnel
stunnel
软件在开机时启动/etc/stunnel
目录中的每个证书文件从一个服务器复制到另一个服务器中stunnel
文件,使其包含: 两个服务器的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进行隧道连接或设置V**。
想要了解更多关于的开源信息教程,请前往腾讯云+社区学习更多知识。
参考文献:《How To Encrypt Traffic to Redis with Stunnel on Ubuntu 16.04》
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。