Redis是一个开源键值数据存储,使用内存存储模型和可选的磁盘写入来实现持久性。它具有事务,发布/订阅消息传递模式以及其他功能之间的自动故障转移功能。Redis的客户使用大多数语言编写,并在其网站上提供推荐的客户。
Redis不提供自己的任何加密功能。它的运作假设它已部署到隔离的专用网络,只能由可信方访问。如果您的环境与该假设不匹配,则必须单独将Redis流量包装在加密中。
在本指南中,我们将演示如何使用名为spiped
的安全管道程序加密Redis流量。Redis客户端和服务器之间的流量将通过专用加密隧道进行路由,类似于专用SSH隧道。我们将使用两台Ubuntu 16.04服务器进行演示。
首先,您应该拥有一sudo
台在每台计算机上都配置了权限的非root用户。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。此外,本指南将假设您已准备好基本防火墙。如果您使用的是腾讯云的CVM服务器,您可以直接在腾讯云控制台中的安全组进行设置。
当您准备好继续时,请按照下面的步骤操作。
该spiped
实用程序易于安装和配置,以便在两个网络套接字(常规网络端口或Unix套接字)之间进行安全通信。它可用于配置两个远程服务器之间的加密通信。客户端连接到本地端口并将其用spiped
包装为加密,然后再将其转发到远程服务器。在服务器端,spiped
侦听已配置的端口并在将流量转发到本地端口(在我们的示例中为Redis服务器侦听的端口)之前解密流量。
使用spiped
的一些优点是:
spiped
包。spiped
加密的流量。一些缺点是:
了解了这些特点之后,让我们开始吧。
在开始之前,我们应该在一台机器上安装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
如果软件已安装并正在运行,您应该看到:
PONG
让我们设置一个以后可以使用的密钥:
redis-cli set test 'success'
我们已将测试键设置为值 success
。配置完成后,我们将尝试从客户端计算机访问此密钥 spiped
.
另一台Ubuntu 16.04机器将作为客户端。我们需要的所有软件都可以在默认存储库的redis-tools
包中找到:
sudo apt-get update
sudo apt-get install redis-tools
使用远程Redis服务器的默认配置和当防火墙处于活动状态时,我们当前无法连接到远程Redis实例从而来进行测试。
接下来,您需要在每个服务器和客户端上安装spiped
。如果您不需要在上一节中安装任何内容,请确保在安装之前包含刷新软件包索引的sudo apt-get update
命令:
sudo apt-get install spiped
现在我们已经安装了必要的软件,我们可以生成一个安全密钥,从而spiped
可以用该密钥来加密我们两台机器之间的流量。
接下来,在Redis服务器上的/etc
中创建一个spiped
配置目录,以存储我们将为加密生成的密钥:
sudo mkdir /etc/spiped
键入以下内容生成安全密钥:
sudo dd if=/dev/urandom of=/etc/spiped/redis.key bs=32 count=1
通过调整权限来限制对生成的密钥文件的访问:
sudo chmod 600 /etc/spiped/redis.key
现在我们在Redis服务器上有密钥,我们可以使用systemd单元文件在服务器上进行spiped
设置。
该spiped
实用程序非常简单,不支持读取配置文件。由于必须手动配置每个管道,因此Ubuntu软件包不附带init脚本以在引导时自动启动管道。
要解决这些问题,我们将创建一个简单的systemd单元文件。在/etc/systemd/system
目录中打开一个新的单元文件以开始:
sudo nano /etc/systemd/system/spiped-receive.service
在内部,创建一个[Unit]
部分来描述单元并建立排序,以便在网络可用后启动该单元:
[Unit]
Description=spiped receive for Redis
Wants=network-online.target
After=network-online.target
接下来,打开一个[Service]
部分以定义要运行的实际命令。我们将用spiped
来使用以下选项:
-F
:在前台运行。systemd init系统旨在尽可能管理在前台运行的服务。在前台运行简化了所需的配置。-d
:解密来自源套接字的流量。这告诉了spiped
关于加密的方向,以便它知道解密来自源的流量并加密来自目标的流量。-s
:这定义了源套接字。IP地址必须在方括号中,后跟冒号,然后是端口。对于Redis服务器,应将其设置为公共IP地址和Redis端口。-t
:目标套接字。这是解密后转发流量的地方。默认情况下,Redis会侦听本地主机上的端口6379,因此这是我们必须使用的。-k
:指定要使用的密钥文件。这应该指向我们之前生成的加密密钥。所有这些选项都将放在一个ExecStart
指令中,这是我们在本节中需要的唯一项目:
[Unit]
Description=spiped receive for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -d -s [redis_server_public_IP]:6379 -t [127.0.0.1]:6379 -k /etc/spiped/redis.key
最后,我们将包含一个[Install]
部分,告诉systemd如果启用,那么何时自动启动该单元:
[Unit]
Description=spiped receive for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -d -s [redis_server_public_IP]:6379 -t [127.0.0.1]:6379 -k /etc/spiped/redis.key
[Install]
WantedBy=multi-user.target
完成后,保存并关闭文件。
键入以下命令启动并启用新spiped
单元:
sudo systemctl start spiped-receive.service
sudo systemctl enable spiped-receive.service
如果您检查在Redis服务器上侦听连接的服务的话,您应该看到spiped
在公共接口上侦听端口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/spiped
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
虽然spiped
正在侦听公共接口,但防火墙可能还没有配置为允许流量通过的状态。
要允许所有流量到端口6379,请键入:
sudo ufw allow 6379
这将打开对spiped
正在侦听的公共接口上的端口6379的访问。该spiped
端口仅接受加密流量。
要将加密密钥传输到客户端,我们需要在两台服务器之间建立安全连接。我们将使用ssh
,因为这允许我们利用我们现有的配置。
如果使用基于密钥的身份验证,则需要将SSH密钥转发到Redis服务器以建立连接。对于基于密码的系统,这不是必需的。
断开与Redis服务器的连接:
exit
现在,在本地计算机上,确保SSH代理正在运行并且已将私钥添加到其中:
eval `ssh-agent`
ssh-add
现在,重新连接到Redis服务器并添加-A
标记以转发密钥:
ssh -A sammy@redis_server_public_IP
您现在可以继续执行以下步骤。
我们将从Redis服务器连接到客户端,因为我们的密钥文件需要本地sudo
权限才能访问。我们现在可以传输文件,确保在命令末尾包含冒号:
sudo -E scp /etc/spiped/redis.key sammy@redis_client_public_IP:
scp
写入客户端计算机上用户的主目录。
传输密钥后,在客户端计算机上创建/etc/spiped
目录:
sudo mkdir /etc/spiped
将加密密钥移动到新目录中:
sudo mv ~/redis.key /etc/spiped
锁定权限以限制访问:
sudo chmod 600 /etc/spiped/redis.key
既然客户端有服务器加密密钥的副本,我们就可以配置的客户端spiped
配置。
我们需要在客户端的spiped
创建一个systemd单元文件,就像我们在Redis服务器上一样。
键入以下内容打开新的systemd单元文件:
sudo nano /etc/systemd/system/spiped-send.service
在里面,打开一个[Unit]
部分来描述服务并确定它取决于网络可用性:e
[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target
接下来,打开一个[Service]
部分来执行该spiped
过程。此处使用的选项与Redis服务器上使用的选项非常相似,但有以下区别:
-e
:指定进入源套接字的流量需要加密。这将建立源套接字和目标套接字之间的关系。-s
:定义源套接字,就像之前一样。但是,在这种情况下,源是本地接口上的任意可用端口,本地Redis客户端可以连接到该端口。-t
:定义目标套接字,就像之前一样。对于客户端,这将是远程Redis服务器的公共IP地址和打开的端口。这些将再次使用ExecStart
指令来设置:
[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -e -s [127.0.0.1]:8000 -t [redis_server_public_IP]:6379 -k /etc/spiped/redis.key
最后,添加一个[Install]
部分来定义启用单元的时间:
[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -e -s [127.0.0.1]:8000 -t [redis_server_public_IP]:6379 -k /etc/spiped/redis.key
[Install]
WantedBy=multi-user.target
完成后,保存并关闭文件。
现在,我们可以在客户端上启动我们的spiped
服务并使其在开启时自动启动:
sudo systemctl start spiped-send.service
sudo systemctl enable spiped-send.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 3264/spiped
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1705/sshd
tcp6 0 0 :::22 :::* LISTEN 1705/sshd
如您所见,spiped
正在侦听本地端口8000以获取连接。
现在,您应该能够通过将客户端指向本地接口上的端口8000来连接到远程的Redis实例:
redis-cli -p 8000 ping
PONG
查询我们在本指南开头设置的测试密钥:
redis-cli -p 8000 get test
"success"
这证实我们能够成功访问远程数据库。
要确认我们无法在不使用隧道的情况下与远程Redis服务器通信,我们可以尝试直接连接到远程端口:
redis-cli -h redis_server_public_IP -p 6379 ping
Error: Protocol error, got "\xac" as reply type byte
如您所见,只有通过隧道正确加密后,才能在远程Redis端口上接受流量。
我们上面概述的示例使用了单个Redis服务器和单个客户端的简单示例。但是,这些相同的方法可以应用于更复杂的交互。
扩展此示例以处理多个客户端非常简单。您需要执行上面列出的以下操作。
spiped
软件包spiped
systemd单元文件复制到新客户端计算机spiped
服务并使其在开启时启动要设置安全的服务器到服务器通信(例如,用于复制或群集),您需要设置两个并行隧道:
spiped
/etc/spiped
目录中spiped
systemd单元文件,以便每个服务器都有一个服务于每个角色的文件: 如有必要,可以在每台计算机上配置多个客户端单元文件,以将本地端口映射到远程服务器。在这些情况下,请确保在发送单元文件中的源套接字规范中选择其他未使用的本地端口。
Redis是一个功能强大且灵活的工具,对许多部署都非常有用。但是,在不安全的环境中运行Redis需要承担巨大的责任,它有可能使您的服务器和数据容易受到攻击或盗窃。如果您没有仅由受信任方填充的隔离网络,则必须通过其他方式保护流量。本指南中概述的方法只是确保Redis各方之间通信的一种方法。其他选项包括使用stunnel进行隧道连接或设置V**。
更多Ubuntu教程请前往腾讯云+社区学习更多知识。
参考文献:《How To Encrypt Traffic to Redis with Spiped on Ubuntu 16.04》
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。