上篇教程我们介绍 Redis 安全隐患的时候提到 Redis 客户端和服务端通信默认是明文传输,而且 Redis 也没有提供诸如 SSL 之类的加密技术支持,要实现类似的安全加密通信,需要借助第三方代理工具。这里我们使用官方推荐的 Spiped 进行演示。
Spiped 加密原理
Spiped 是一个专门用来做对称加密和服务认证的实用工具,它的工作原理和 SSH 通道有些类似,但并不使用 SSH 协议,而是依赖于一个认证双方共享的安全密钥对通信进行对称加密。
对于未使用加密代理的 Redis 客户端和服务端,通信链路如下:
对于使用 Spiped 加密的 Redis 客户端和服务端,通信链路如下:
左边的 Spiped 客户端进程会接收来自 Redis 客户端发送的请求指令,经过加密后发送给右边的 Spiped 服务端进程;服务端 Spiped 将接收到的请求数据解密后发送给 Redis 服务端进行处理,最后 Redis 服务端将响应结果通过一个反向的流程回复给 Redis 客户端。
可以看到,Spiped 进程必须成对出现,一端用于加密数据,另一端用于解密数据,并且客户端和服务端的 Spiped 进程都有一个监听端口用于接收 Redis 客户端/服务端发送的数据。
不过这里是为了方便理解命名了 spiped-client
和 spiped-server
,其实他们两者的地位是完全对等的,当 Redis 客户端发送指令时,左侧 Spiped 是发送数据的「客户端」,右侧 Spiped 是接收数据的「服务端」,而当 Redis 服务端返回响应结果时,右侧的 Spiped 是发送数据的「客户端」,左侧的 Spiped 是接收数据的「服务端」。
由于加密数据可以被解密,所以这个加密是对称加密。
基于 Spiped 加密通信数据
接下来,学院君以 Mac 环境为例来给大家简单演示下如何基于 Spiped 加密 Redis 客户端和服务端通信数据。
开始之前,需要安装 Spiped 软件:
brew install spiped
如果是 Ubuntu 或者 CentOS 系统,将
brew
调整为apt
或者yum
即可。
然后启动 Redis 服务器:
redis-server
如果是 Ubuntu 或者 CentOS 系统,将其调整为对应的 Redis 服务启动指令。
接下来,需要启动两个 Spiped 进程,分别用于加密 Redis 客户端请求和解密请求数据并发送给 Redis 服务端,如果是在生产环境,两个进程需要分别在 Redis 服务端和客户端所在机器启动,不过这里我们是在本地测试,所以都在本地启动,只需要通过端口号进行区分即可。
另外,Spiped 是基于对称加密进行数据加密解密的,因此,在启动这两个进程前,还要先生成密钥信息,我们可以通过如下这个指令快速生成包含 32 位随机密钥的 spiped.key
文件:
dd if=/dev/urandom bs=32 count=1 of=spiped.key
然后我们基于这个密钥文件启动 Spiped 服务端进程:
spiped -d -s '[192.168.31.218]:6378' -t '[127.0.0.1]:6379' -k spiped.key
其中
-d
表示对接收到的数据进行解密(decrypt),-s
用于设置服务端 Spiped 进程 Socket 地址(需要注意,这里的 IP 地址是本地主机的内网 IP 地址,不能设置为127.0.0.1
,如果不限制客户端 IP,可以将其设置为0.0.0.0
),-t
用于指定解密后的 Redis 请求转发目标,即 Redis 服务端 Socket 地址,-k
用于指定包含密钥的文件。
再启动 Spiped 客户端进程:
spiped -e -s '[192.168.31.218]:6377' -t '[192.168.31.218]:6378' -k spiped.key
其中
-e
表示对接收到的数据进行加密(encrypt),-s
、-t
、-k
和上面服务端启动进程含义一样,不同之处在于,Spiped 客户端需要将加密数据转发给 Spiped 服务端,同样这里的 IP 地址都是本地主机的内网 IP 地址。
至此我们已经完成了 Spiped 客户端、服务端、Redis 服务端的启动,最后,可以通过 Redis 客户端连接到 Spiped 客户端,以便通过 Spiped 来加密 Redis 请求数据:
redis-cli -h 192.168.31.218 -p 6377
这里,
-h
和-p
选项需要和 Spiped 客户端进程所在的 IP 地址和监听的端口号保持一致。
可以看到,请求处理成功,Spiped 只在中间扮演了代理加密解密的角色,所有指令可以照常执行,对使用 Redis 客户端的业务方和 Redis 服务端而言是无感知的。
本系列教程首发在Laravel学院(laravelacademy.org),你可以点击页面左下角阅读原文链接查看最新更新的教程。