在服务器上启用加密连接有点像编织一个魔法咒语:在您完全正确地念出咒语之前,一切都不会工作,但是一旦您做到了,一切都会自动就位,并且您已经建立了与服务器的安全连接。当您还使用密码学来验证连接上的客户端时,配置加密可能会变得更加神秘。
启用与服务器的安全连接应成为每位开发人员的必备技能,因此在本文中,我们将引导您完成一个简单的三步过程,以使用 SSL 启用、测试和配置 Redis Enterprise Cloud 与 Python 客户端之间的加密连接。
如果您想一起操作,您需要获取以下工具 - 我们会等您安装它们
您的 Redis Enterprise Cloud 订阅必须启用 SSL 功能才能使用 SSL。如果您的帐户尚未启用 SSL,则需要联系 Redis 支持团队来为您的订阅启用 SSL。您可以在帐户仪表板的主菜单中找到联系支持团队的链接。
有关设置 SSL的文档可以在 Redis Enterprise Cloud 操作和管理指南中找到,但在本文中,我们将引导您完成使用 SSL 与 Python 客户端所需的所有步骤。步骤 1 和 2 恰好适用于任何语言,我们将在以后的 Java 相关文章中再次提到它们。
SSL,或安全套接字层,是一种用于保护客户端和服务器之间连接的标准协议。 SSL 使用加密来确保客户端和服务器之间传输的任何数据保持私密性。 SSL 还使用公钥密码学来验证客户端和服务器。 密码学验证是可选的,但几乎总是服务器的要求。 TLS(传输层安全性)是 SSL 协议的后继者,并且具有相同的功能。
缩写“SSL”非正式地用于指代 SSL 或 TLS 安全的连接。 Redis Enterprise Cloud 的文档和管理 UI 遵循该约定。 在本文中,我们将遵循文档约定并使用“SSL”来指代 SSL 和 TLS。
截至 2018 年 6 月,Redis Enterprise Cloud 使用 TLS 1.2 版来保护数据库和服务器之间的连接。
当然,将 SSL 与 Redis Enterprise Cloud 结合使用的第一步是为我们的数据库启用 SSL。 首先登录到您的 Redis Enterprise Cloud 帐户并创建一个您可以试验的新数据库。 在您逐步完成数据库创建过程时,您将进入创建数据库页面。 到达创建数据库页面后(您也可以从编辑数据库页面启用 SSL),找到访问控制和安全性组,然后启用SSL 客户端身份验证。
客户端身份验证(有时缩短为 Client-AUTH)是 SSL 规范的可选部分,除了服务器之外,还需要客户端通过公钥密码学进行身份验证。 尽管它是 TLS 协议的可选部分,但 Redis Enterprise Cloud 需要 Client-AUTH 才能使用 SSL。 启用SSL 客户端身份验证后,您的客户端软件将需要使用密码和公钥进行身份验证。 在 SSL 中,公钥信息通过数字证书进行交换。
作为启用SSL 客户端身份验证的一部分,我们可以让 Redis Enterprise Cloud 为我们的客户端生成证书。 按下生成客户端证书按钮,系统将为您的客户端生成证书。 按下该按钮还会导致您的浏览器下载凭据的 zip 文件 (redis_credentials.zip),并在“客户端证书”字段中填充客户端证书的 PEM 版本。
您可以将为您的客户端创建的证书视为一个数字 ID,它可以用来证明其身份。 该证书由颁发证书的组织进行数字签名,以确保其未被修改。
redis_credentials.zip 文件包含相互验证客户端和服务器所需的所有文件的副本。 此存档包括为您的客户端生成的证书 (redis_user.crt)、相应的私钥 (redis_user_private.key) 以及 Redis 证书颁发机构的证书副本 (redis_ca.pem)。 需要特别注意 redis_credentials.zip 文件和 redis_user_private.key,以确保密钥的安全。 所有这三个文件都需要分发到连接到此特定 Redis 数据库实例的每个客户端,因此您需要将它们集成到用于管理已部署软件的凭据的系统中。
为新的软件设置 SSL 连接通常是一种令人沮丧的体验; 在您将所有组件都安装到位之前,没有任何东西可以工作,但是随后一切都可以正常工作。 SSL 问题本质上很难调试,这无济于事。 毕竟,该协议旨在防止您知道线上传输的内容! 因此,在使用 SSL 与我们的客户端代码之前,我们将测试我们是否可以使用OpenSSL s_client 命令与数据库建立安全连接。
使用您在步骤 1 中下载的 redis_credentials.zip 中的凭据,在您放置提取文件的目录中运行以下命令
openssl s_client -host [endpoint name] -port [endpoint port number] -cert redislabs_user.crt -key redislabs_user_private.key -CAfile redislabs_ca.pem -crlf
从您在步骤 1 中使用的数据库中获取主机参数的端点名称和端口参数的 endport 端口。使用此命令,OpenSSL 将尝试与您的 Redis 实例建立安全 TLS 连接,并打印服务器提供的证书。 运行该命令将产生关于 TLS 连接各个方面的长序列输出,并在末尾显示一条类似于以下内容的消息
Verify return code: 0 (ok)
如果您看到任何其他返回代码或消息,则无法安全地建立连接。
如果您无法建立安全连接,请确保您已在数据库实例上正确启用了 TLS 客户端身份验证,并且您已为要连接的实例下载了相应的凭据文件。 一旦您可以使用 OpenSSL 成功连接到您的数据库,那么为您的客户端启用 SSL。 相信我——不要跳过这一步!
最后一步是修改您的客户端代码以建立 SSL 连接。 我们将在 Python 中构建一个示例客户端,以建立与我们的 Redis Enterprise Cloud 实例的安全连接。 我们的示例客户端将连接到数据库并运行Redis INFO 命令。 我们的客户端代码如下:
#!/usr/local/bin/python3
import redis
import pprint
try:
r = redis.StrictRedis(
decode_responses=True,
host='redis-16148.c15.us-east-1-2.ec2.cloud.redislabs.com',
port=16148,
password='sekret',
ssl=True,
ssl_keyfile='./redislabs_user_private.key',
ssl_certfile='./redislabs_user.crt',
ssl_cert_reqs='required',
ssl_ca_certs='./redislabs_ca.pem',
)
info = r.info()
pprint.pprint(info)
except Exception as err:
print("Error connecting to Redis: {}".format(err))
我们的客户端代码与不使用 SSL 的版本几乎相同,我们只需要向 StrictRedis 构造函数添加五个额外的参数:ssl、ssl_keyfile、ssl_certfile、ssl_cert_reqs 和 ssl_ca_certs。 第一个参数 ssl 只是在连接上启用 SSL。 其余参数用于提供相互验证客户端和服务器所需的凭据。 请务必注意,您仍然必须为实例提供密码,该密码可以在“编辑数据库”屏幕上找到。
redis-py 客户端redis-py client使用Python 3 ssl 包为与 Redis 的标准套接字连接提供 SSL 包装器。 在底层,“ssl”前缀的参数是关键字参数,映射到 ssl.wrap_socket 方法的参数。 可以在 ssl 包文档中找到参数的详细文档。
客户端需要验证自身的凭据——它的证书和私钥(我们在第一部分中下载的)——使用 ssl_keyfile 和 ssl_certfile 参数提供给 SSL 库。 Python SSL 库直接与 Redis Enterprise Cloud 生成的 PEM 文件格式一起使用。
ssl_cert_reqs 参数转换为SSLContext.verify_mode的值,并控制服务器必须如何进行身份验证。 此参数可以采用三个不同的值之一:none、optional 或 required。 在使用 Redis Enterprise Cloud 时,您应始终以 ssl_cert_reqs 设置为 required 的状态运行。 默认情况下,SSL 库使用操作系统附带的证书(其中包括所有主要的证书颁发机构)来验证服务器。 由于 Redis 维护自己的证书颁发机构,因此您需要向 SSL 库提供 Redis 证书颁发机构的证书 (redis_ca.pem),以便 SSL 库可以验证服务器身份。
一旦 StrictRedis 构造函数被更改为设置 SSL 并加载验证客户端和服务器所需的所有凭据,你就可以运行代码并查看它是如何连接到数据库的。作为一项实验,尝试删除 ssl_keyfile 和 ssl_certfile 参数,看看脚本如何验证失败。之后,添加回 ssl_keyfile 和 ssl_certfile 参数,并删除 ssl_ca_cert 参数,看看客户端这次如何响应。
配置 redis-py 以使用 SSL 并不是特别困难,但第一次操作时可能会令人恼火。 SSL 的设计是为了确保你的通信安全,因此你可能会一直收到错误(并且似乎没有任何进展),直到一切都设置正确为止。
希望这篇文章能为你提供一个关于设置与 Redis Enterprise Cloud 的安全连接并将 SSL 添加到你的项目所需的组件的简单介绍。 在后续文章中,我们将详细介绍如何设置 Redis Enterprise Cloud 和 Java 客户端之间的安全连接。
最后提醒一下:许多组织都有关于安全性和管理这些凭据的特定策略,因此请务必与你的运营或安全团队合作,以确保你遵循所有适用的策略。