如何在Ubuntu16.04上使用Spiped加密到Redis的流量

来自菜鸟教程
跳转至:导航、​搜索

介绍

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

Redis 本身不提供任何加密功能。 它的运行假设是它已部署到一个隔离的专用网络,只有受信任的方可以访问。 如果您的环境不符合该假设,您将不得不单独将 Redis 流量包装在加密中。

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

先决条件

首先,您应该在每台机器上配置一个具有 sudo 权限的非 root 用户。 此外,本指南将假设您有一个基本的防火墙。 您可以按照我们的 Ubuntu 16.04 初始服务器设置指南 来满足这些要求。

当您准备好继续时,请按照以下说明进行操作。

什么是加料?

spiped 实用程序易于安装和配置,用于两个网络套接字(常规网络端口或 Unix 套接字)之间的安全通信。 它可用于配置两个远程服务器之间的加密通信。 客户端连接到本地端口,spiped 在将其转发到远程服务器之前对其进行加密包装。 在服务器端,spiped 侦听配置的端口并解密流量,然后将其转发到本地端口(在我们的例子中,Redis 服务器侦听的端口)。

使用 spiped 的一些优点是:

  • Ubuntu 在其默认存储库中维护 spiped 的软件包。
  • Redis 项目目前建议 使用 spiped 来加密流量。
  • 配置简单直观。
  • 每种用途都使用一条新管道。 在某些情况下,这可能是一个缺点,但它提供了对访问的精细控制。

一些缺点是:

  • 客户端通过附加到非默认本地端口来连接到远程机器,这起初可能不直观。
  • 如果连接两台 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'

我们已将 test 键设置为值 success。 在配置 spiped 后,我们将尝试从我们的客户端计算机访问此密钥。

安装 Redis 客户端

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

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

由于远程 Redis 服务器的默认配置和防火墙处于活动状态,我们目前无法连接到远程 Redis 实例进行测试。

在每台计算机上安装 spiped

接下来,您需要在每个服务器和客户端上安装 spiped。 如果您不需要在上一节中安装任何东西,请确保在安装前包含 sudo apt-get update 命令以刷新您的包索引:

sudo apt-get install spiped

现在我们已经安装了必要的软件,我们可以生成一个安全密钥,spiped 可以使用它来加密我们两台机器之间的流量。

在 Redis 服务器上生成加密密钥

接下来,在您的 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

为 Redis 服务器创建一个 systemd 单元文件

spiped 实用程序非常简单,它不支持读取配置文件。 因为必须手动配置每个管道,所以 Ubuntu 软件包没有附带一个 init 脚本来在启动时自动启动管道。

为了解决这些问题,我们将创建一个简单的 systemd 单元文件。 在/etc/systemd/system目录下打开一个新的单元文件开始:

sudo nano /etc/systemd/system/spiped-receive.service

在里面,创建一个 [Unit] 部分来描述单元并建立顺序,以便在网络可用后启动这个单元:

/etc/systemd/system/spiped-receive.service

[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 指令中,这是我们在本节中唯一需要的项目:

/etc/systemd/system/spiped-receive.service

[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 如果启用,何时自动启动该单元:

/etc/systemd/system/spiped-receive.service

[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服务并调整Redis服务器上的防火墙

通过键入以下命令启动并启用新的 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 配置的客户端。

为 Redis 客户端创建一个 systemd 单元文件

我们需要在客户端为 spiped 创建一个 systemd 单元文件,就像我们在 Redis 服务器上所做的那样。

通过键入以下命令打开一个新的 systemd 单元文件:

sudo nano /etc/systemd/system/spiped-send.service

在里面,打开 [Unit] 部分来描述服务并确定它取决于网络可用性:

/etc/systemd/system/spiped-send.service

[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target

接下来,打开一个 [Service] 部分来执行 spiped 进程。 这里使用的选项与 Redis 服务器上使用的选项非常相似,但有以下区别:

  • -e:指定进入源套接字的流量需要加密。 这建立了源套接字和目标套接字之间的关系。
  • -s:定义源套接字,和以前一样。 但是,在这种情况下,源是本地 Redis 客户端可以连接到的本地接口上的任意可用端口。
  • -t:定义目标socket,和之前一样。 对于客户端,这将是远程 Redis 服务器的公共 IP 地址和打开的端口。

这些将再次使用 ExecStart 指令设置:

/etc/systemd/system/spiped-send.service

[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] 部分来定义如果启用,该单元何时启动:

/etc/systemd/system/spiped-send.service

[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 服务并测试连接

现在,我们可以在客户端启动我们的 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
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: Protocol error, got "\xac" as reply type byte

如您所见,只有在通过隧道正确加密的情况下,远程 Redis 端口才接受流量。

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

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

扩展此示例以处理多个客户端很简单。 您需要执行上述操作。

  • 在新客户端上安装 Redis 客户端软件和 spiped
  • 将加密密钥传输到新客户端
  • spiped systemd 单元文件复制到新的客户端机器
  • 启动spiped服务并使其开机启动

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

  • 在新服务器上,安装 Redis 服务器包和 spiped
  • 为新的 Redis 服务器生成一个新的加密密钥(为文件使用唯一的名称)
  • 将加密密钥从一台服务器复制到另一台服务器到 /etc/spiped 目录
  • 在每个服务器(包括现有服务器)上创建一个 spiped systemd 单元文件,以便每个服务器都有一个文件服务于每个角色:
    • 将外部端口映射到本地 Redis 的接收单元文件
    • 将本地端口映射到远程服务器公开端口的发送单元文件
  • 在新的 Redis 服务器上打开防火墙中的外部端口
  • 通过调整 Redis 配置文件配置每个 Redis 实例连接到本地映射的端口以访问远程服务器(所需的指令取决于服务器的关系。 有关更多详细信息,请参阅 Redis 文档)。

如有必要,可以在每台机器上配置多个客户端单元文件,以将本地端口映射到远程服务器。 在这些情况下,请务必在发送单元文件的源套接字规范中选择不同的未使用本地端口。

结论

Redis 是一个功能强大且灵活的工具,对于许多部署来说都是无价的。 但是,在不安全的环境中运行 Redis 是一项巨大的责任,会使您的服务器和数据容易受到攻击或盗窃。 如果您没有仅由受信任方组成的隔离网络,则必须通过其他方式保护流量。 本指南中概述的方法只是保护 Redis 各方之间通信的一种方法。 其他选项包括 隧道与 stunnel设置 VPN