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

Redis是一个开源的键值数据存储,使用具有可选磁盘写入的内存存储模型进行持久化。它具有事务,发布/订阅消息模式和自动故障切换等功能。 Redis有大多数语言的客户端...

介绍

Redis是一个开源的键值数据存储,使用具有可选磁盘写入的内存存储模型进行持久化。它具有事务,发布/订阅消息模式和自动故障转移等功能。Redis的客户端用大多数语言编写,推荐他们的网站 。 Redis不提供自己的任何加密功能。它的操作假设它已经部署到一个孤立的专用网络,只有信任方才能访问。如果您的环境不匹配该假设,您将必须单独加密Redis流量加密。 在本指南中,我们将演示如何使用一个被称为安全隧道程序加密Redis的流量stunnel 。 Redis客户端和服务器之间的流量将通过专用的SSL加密隧道进行路由。我们将使用两个Ubuntu 16.04服务器来演示。

先决条件

要开始,你应该有一个非root用户sudo在每个机器的配置权限。 此外,本指南假设您有一个基本的防火墙。 您可以按照我们的Ubuntu 16.04服务器初始设置指南 ,以满足这些要求。 当您准备好继续,请按照下面。

什么是stunnel?

对于基本的加密通信的stunnel实用工具是简单的安装和配置。 它实现两台机器之间的加密转发。 客户端连接到本地端口和stunnel把它封装在加密转发到远程服务器之前。 在服务器端, stunnel监听配置的端口上,并转发到一个本地端口之前解密的流量(在我们的情况下,Redis的服务器监听的端口)。 使用的一些优点stunnel是:
  • Ubuntu的维护包stunnel在其默认库
  • 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
类型输入在此过程中接受的提示。 安装完成后,请测试您是否可以通过键入以下内容连接到Redis服务:
redis-cli ping
如果软件已安装并运行,您应该会看到:
PONG
让我们设置一个我们以后可以使用的密钥:
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
stunnel上的Ubuntu服务使用的旧的SysVinit脚本启动时,可以通过systemd管理。 而不是使用本地systemd方法来配置服务在引导时启动,你必须修改/etc/default/stunnel4文件:
sudo nano /etc/default/stunnel4
启用该服务通过设置开机后自动启动ENABLED选项设置为“1”:
/ etc / default / stunnel4
. . .
ENABLED=1
. . .
保存并关闭每个服务器上的文件。 接下来,我们将创建一个自签名的SSL证书和密钥,用于加密通信。

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

在您的Redis的服务器上,创建了一个自签名的SSL证书和密钥/etc/stunnel目录。 这将被用于的两个实例之间的连接进行加密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
系统将提示您输入有关要创建的证书的信息。由于这只会在内部使用,所以值不要太大,所以填写任何你想要的。您可以看到以下示例:
. . .
-----
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配置文件

打开结尾的文件.conf的范围内/etc/stunnel Redis的服务器上的目录开始:
sudo nano /etc/stunnel/redis.conf
在里面,指定一个位置在主要部分中写入PID文件。该/run目录旨在存储这些类型的文件,所以我们将使用:
/etc/stunnel/redis.conf
pid = /run/stunnel-redis.pid
接下来,创建一个部分以配置对Redis服务的访问。您可以拨打这个任何你想(我们称之为redis-server )。该部分将此配置与您以后可能需要在此机器上配置的任何其他隧道分离。 我们需要指定Redis的服务器自己的证书,并使用该密钥的位置certkey分别指令。 我们还将在这里定义传入数据的隧道。我们要accept加密流量对Redis的服务器的外部IP地址,默认Redis的端口(端口6379)。 然后,我们要connect流量的默认端口Redis的本地接口上存解密的流量。这是Redis服务实际上在侦听的地方:
/etc/stunnel/redis.conf
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并配置防火墙

现在, stunnel是Redis的服务器上配置,我们可以通过键入重新启动服务:
sudo systemctl restart stunnel4.service
如果您检查聆听您的Redis服务器上的连接服务,你应该看到stunnel的公共接口上侦听端口6379。您还应该看到Redis正在本地接口上侦听同一个端口:
sudo netstat -plunt
Active 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
这将打开访问端口6379的公共接口,其中的stunnel被监听。 该stunnel端口只接受加密的流量。

将证书分发给客户端

每个Redis客户端将需要一个Redis服务器的证书文件的副本。分发的最简单的方法.crt文件是简单地输出在服务器上的文件的内容,然后将内容复制到相应的文件在连接机器。 输出的内容.crt您的Redis服务器上的文件通过键入:
cat /etc/stunnel/redis-server.crt
-----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配置。 打开结尾的文件.conf/etc/stunnel在客户机上的目录。 我们将调用文件redis.conf再次:
sudo nano /etc/stunnel/redis.conf
在里面,指定一个PID文件,服务将再次存储其进程ID:
/etc/stunnel/redis.conf
pid = /run/stunnel-redis.pid
接下来,添加一个部分以配置出站数据的隧道。您可以命名这个无论你想(我们称之为redis-client )。该部分将此配置与您以后可能需要在此机器上配置的任何其他隧道分离。 我们需要明确标注本条使用的客户端配置client指令。 将accept指令,未使用的端口上侦听的本地接口上,以处理从本地Redis的客户端连接(我们将使用8000端口在这个例子中)。 将connect指令Redis的服务器的公网IP地址,我们打开的端口。 然后使用CAfile指向的Redis服务器证书的复印件。 我们还必须设置verify为4,这使得stunnel只检查证书而不考虑的证书链(因为我们自签名的证书,我们的):
/etc/stunnel/redis.conf
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
Active 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
PONG
查询我们在本指南开头设置的测试键:
redis-cli -p 8000 get test
"success"
这确认我们能够成功地到达远程数据库。 为了证实我们无法在不使用的隧道与远程服务器Redis的沟通,我们可以尝试直接连接到远程端口:
redis-cli -h redis_server_public_IP -p 6379 ping
Error: 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