如何在Ubuntu18.04上保护您的Redis安装
介绍
Redis 是一种内存中的 NoSQL 键值缓存和存储,也可以持久化到磁盘。 它是为 受信任的客户端 在 受信任的环境 中使用而设计的,它本身没有强大的安全功能。 为了强调这一点,这里引用 官方 Redis 网站 的一段话:
Redis 旨在由受信任环境中的受信任客户端访问。 这意味着通常将 Redis 实例直接暴露给 Internet 或者通常暴露给不受信任的客户端可以直接访问 Redis TCP 端口或 UNIX 套接字的环境不是一个好主意。
. . .
通常,Redis 并未针对最大安全性进行优化,而是针对最大性能和简单性进行了优化。
尽管如此,Redis 确实内置了一些基本的安全功能。 其中包括创建未加密密码的能力以及重命名和禁用命令的自由。 值得注意的是,它缺乏真正的访问控制系统。
这些功能本身并不能确保您的 Redis 安装的安全性。 但是,配置它们仍然是让您的数据库完全不安全的一大步。
在本教程中,您将了解如何配置 Redis 具有的一些安全功能,并对系统配置进行一些更改,这将提高 Ubuntu 服务器上独立 Redis 安装的安全性。
请注意,本指南不涉及 Redis 服务器和客户端应用程序位于不同主机或不同数据中心的情况。 Redis 流量必须穿过不安全或不受信任的网络的安装需要一组完全不同的配置,例如在 Redis 机器之间设置 SSL 代理或 VPN,除了此处给出的配置。
先决条件
对于本教程,您需要:
- 一个 Ubuntu 18.04 服务器。 此服务器还应该有一个具有
sudo
权限的非 root 用户以及使用 UFW 设置的防火墙,您可以按照我们的 Ubuntu 18.04 初始服务器设置指南进行配置。 - 在您的服务器上安装和配置 Redis。 您可以按照 this guide for Ubuntu 18.04 servers 进行设置。
第 1 步 - 验证 Redis 是否正在运行
首先,使用非 root 用户通过 SSH 连接到您的服务器。
要检查 Redis 是否正常工作,请使用 redis-cli
命令打开 Redis 命令行:
redis-cli
注意:如果你已经为Redis设置了密码,连接后必须使用auth
命令进行认证:
auth your_redis_password
OutputOK
如果您尚未为 Redis 设置密码,您可以在本教程的第 4 步中阅读如何设置。
使用 ping
命令测试连接:
ping
如果 Redis 工作正常,您将看到以下内容:
OutputPONG
在此之后,退出 Redis 命令行:
quit
现在您已经确认 Redis 正在运行并正常工作,您可以继续进行增强服务器安全性的最重要步骤:配置防火墙。
第 2 步 — 使用 UFW 保护服务器
Redis 只是一个在您的服务器上运行的应用程序。 因为它自己只有一些基本的安全功能,所以真正保护它的第一步是保护它运行的服务器。 对于像 Ubuntu 18.04 服务器这样的面向公众的服务器,第一步是按照 Initial Server Setup Guide for Ubuntu 18.04 中的说明配置防火墙。 如果您还没有这样做,请点击该链接并立即设置您的防火墙。
如果您不确定是否设置了防火墙或者它是否处于活动状态,您可以通过运行以下命令进行检查:
sudo ufw status
如果您遵循 Ubuntu 18.04 的初始服务器设置指南,您将看到以下输出:
OutputStatus: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6)
如果您已使用该指南实施了防火墙规则,则无需为 Redis 添加额外规则,因为默认情况下,除非明确允许,否则 UFW 会丢弃所有传入流量。 由于 Redis 服务器的默认独立安装仅侦听环回接口(127.0.0.1
或 localhost),因此无需担心其默认端口上的传入流量。
有关如何添加规则的更多信息,请参阅此 通用 UFW 规则和命令指南 。
第 3 步 - 绑定到 localhost
默认情况下,Redis 只能从 localhost 访问。 但是,如果您按照与先决条件部分中给出的教程不同的教程来配置 Redis,您可能已经更新了配置文件以允许从任何地方进行连接。 这不如绑定到 localhost 安全。
打开 Redis 配置文件进行编辑:
sudo nano /etc/redis/redis.conf
找到此行并确保它未注释(如果存在则删除 #
):
/etc/redis/redis.conf
bind 127.0.0.1
完成后保存并关闭文件(按 CTRL + X
、Y
,然后按 ENTER
)。
然后,重新启动服务以确保 systemd 读取您的更改:
sudo systemctl restart redis
要检查此更改是否生效,请运行以下 netstat
命令:
sudo netstat -lnp | grep redis
Outputtcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 2855/redis-server 1
此输出显示 redis-server
程序绑定到 localhost (127.0.0.1
),反映了您刚刚对配置文件所做的更改。 如果您在该列中看到另一个 IP 地址(例如 0.0.0.0
),那么您应该仔细检查您是否取消了正确的行并重新启动 Redis 服务。
现在您的 Redis 安装仅在 localhost 上侦听,恶意行为者将更难以发出请求或访问您的服务器。 但是,Redis 目前并未设置为要求用户在更改其配置或它所持有的数据之前进行身份验证。 为了解决这个问题,Redis 允许您在通过 Redis 客户端 (redis-cli
) 进行更改之前要求用户使用密码进行身份验证。
第 4 步 — 配置 Redis 密码
配置 Redis 密码可启用其两个内置安全功能之一 - auth
命令,该命令需要客户端进行身份验证才能访问数据库。 密码直接在 Redis 的配置文件 /etc/redis/redis.conf
中配置,因此请使用您喜欢的编辑器再次打开该文件:
sudo nano /etc/redis/redis.conf
滚动到 SECURITY
部分并查找注释指令,内容如下:
/etc/redis/redis.conf
# requirepass foobared
通过删除 #
取消注释,并将 foobared
更改为安全密码。
注:在redis.conf
文件中的requirepass
指令上方,有一条注释警告:
/etc/redis/redis.conf
# Warning: since Redis is pretty fast an outside user can try up to # 150k passwords per second against a good box. This means that you should # use a very strong password otherwise it will be very easy to break. #
因此,指定一个非常强且非常长的值作为密码非常重要。 您可以使用 openssl
命令生成一个随机密码,而不是自己编写密码,如下例所示。 第二个 openssl
命令的管道将删除第一个命令输出的任何换行符:
openssl rand 60 | openssl base64 -A
您的输出应类似于:
OutputRBOJ9cCNoGCKhlEBwQLHri1g+atWgn4Xn4HwNUbtzoVxAYxkiYBi7aufl4MILv1nxBqR4L6NNzI0X6cE
将该命令的输出复制并粘贴为 requirepass
的新值后,应显示为:
/etc/redis/redis.confrequirepass RBOJ9cCNoGCKhlEBwQLHri1g+atWgn4Xn4HwNUbtzoVxAYxkiYBi7aufl4MILv1nxBqR4L6NNzI0X6cE
设置密码后,保存文件,重启Redis:
sudo systemctl restart redis.service
要测试密码是否有效,请访问 Redis 命令行:
redis-cli
下面显示了用于测试 Redis 密码是否有效的一系列命令。 第一个命令尝试在身份验证之前将密钥设置为值:
set key1 10
这不起作用,因为您没有进行身份验证,因此 Redis 返回错误:
Output(error) NOAUTH Authentication required.
下一条命令使用 Redis 配置文件中指定的密码进行身份验证:
auth your_redis_password
Redis 承认:
OutputOK
之后,再次运行之前的命令就会成功:
set key1 10
OutputOK
get key1
向 Redis 查询新键的值。
get key1
Output"10"
验证通过后确认可以在Redis客户端运行命令后,可以退出redis-cli
:
quit
接下来,我们将研究重命名 Redis 命令,如果输入错误或由恶意行为者输入,可能会对您的机器造成严重损坏。
第 5 步 - 重命名危险命令
Redis 内置的其他安全功能涉及重命名或完全禁用某些被认为是危险的命令。
当错误或未经授权的用户运行时,此类命令可用于重新配置、销毁或以其他方式擦除您的数据。 与验证密码一样,重命名或禁用命令在 /etc/redis/redis.conf
文件的相同 SECURITY
部分中配置。
一些被认为是危险的命令包括:FLUSHDB、FLUSHALL、KEYS、PEXPIRE、DEL、 CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, [X252X ]SREM、RENAME 和 DEBUG。 这不是一个完整的列表,但是重命名或禁用该列表中的所有命令是增强 Redis 服务器安全性的一个很好的起点。
您是否应该禁用或重命名命令取决于您或您的站点的特定需求。 如果你知道你永远不会使用可能被滥用的命令,那么你可以禁用它。 否则,重命名它可能符合您的最佳利益。
要启用或禁用 Redis 命令,请再次打开配置文件:
sudo nano /etc/redis/redis.conf
警告: 以下显示如何禁用和重命名命令的步骤是示例。 您应该只选择禁用或重命名对您有意义的命令。 您可以在 redis.io/commands 上自行查看完整的命令列表并确定它们可能被滥用的方式。
要禁用命令,只需将其重命名为空字符串(由一对引号表示,它们之间没有其他字符),如下所示:
/etc/redis/redis.conf
. . . # It is also possible to completely kill a command by renaming it into # an empty string: # rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command DEBUG "" . . .
要重命名命令,请为其指定另一个名称,如下例所示。 重命名的命令应该很难让别人猜到,但很容易记住:
/etc/redis/redis.conf
. . . rename-command CONFIG "" rename-command SHUTDOWN SHUTDOWN_MENOT rename-command CONFIG ASC12_CONFIG . . .
保存更改并关闭文件。
重命名命令后,通过重新启动 Redis 应用更改:
sudo systemctl restart redis.service
要测试新命令,请输入 Redis 命令行:
redis-cli
接下来,进行身份验证:
auth your_redis_password
OutputOK
假设您将 CONFIG
命令重命名为 ASC12_CONFIG
,如前面的示例所示。 首先,尝试使用原始的 CONFIG
命令。 它应该失败,因为您已将其重命名:
config get requirepass
Output(error) ERR unknown command 'config'
但是,调用重命名的命令会成功。 它不区分大小写:
asc12_config get requirepass
Output1) "requirepass" 2) "your_redis_password"
最后,可以从redis-cli
退出:
exit
请注意,如果您已经在使用 Redis 命令行,然后重新启动 Redis,则需要重新进行身份验证。 否则,如果您键入命令,您将收到此错误:
OutputNOAUTH Authentication required.
关于重命名命令的做法,在 /etc/redis/redis.conf
的 SECURITY
部分末尾有一个警告声明,内容如下:
Please note that changing the name of commands that are logged into the AOF file or transmitted to slaves may cause problems.
笔记: Redis 项目选择使用术语“master”和“slave”,而 DigitalOcean 通常更喜欢使用“primary”和“secondary”的替代词。 为了避免混淆,我们选择在这里使用 Redis 文档中使用的术语。
这意味着如果重命名的命令不在 AOF 文件中,或者如果在 AOF 文件中但 AOF 文件没有传输到从站,那么应该没有问题。
因此,当您尝试重命名命令时请记住这一点。 重命名命令的最佳时间是不使用 AOF 持久性时,或者在安装之后,即在使用 Redis 的应用程序部署之前。
当您使用 AOF 并处理主从安装时,请考虑 这个来自项目的 GitHub 问题页面 的答案。 以下是对作者问题的回复:
命令会记录到 AOF 并以与发送相同的方式复制到从属设备,因此如果您尝试在没有相同重命名的实例上重放 AOF,您可能会遇到不一致,因为无法执行命令(奴隶也一样)。
因此,在这种情况下处理重命名的最佳方法是确保将重命名的命令应用于主从安装中的所有实例。
结论
请记住,一旦有人登录到您的服务器,就很容易绕过我们设置的特定于 Redis 的安全功能。 因此,最重要的安全功能是您的防火墙,这使得恶意行为者很难越过这道栅栏。
如果您尝试在不受信任的网络上保护 Redis 通信,则必须按照 Redis 开发人员在 官方 Redis 安全指南 中的建议使用 SSL 代理。