Redis默认配置如果直接暴露在公网或内网中,几乎等于把数据库大门敞开。最常见的入侵路径是未设置密码或使用弱密码,攻击者通过扫描6379端口,一旦连接成功就能执行FLUSHALL清空数据,甚至利用CONFIG SET dir和CONFIG SET dbfilename把公钥写入目标服务器,实现SSH免密登录。所以第一件事不是调参数,而是确认你的Redis是否设置了requirepass,并且密码强度足够。很多事故复盘里,问题都出在“为了方便”四个字上。
设置密码只是基础。Redis的指令设计初衷是给可信内网用的,很多高危命令没有二次鉴权。比如KEYS *、FLUSHDB、FLUSHALL、CONFIG、SHUTDOWN、DEBUG、EVAL等,一旦被未授权调用,轻则性能雪崩,重则数据全毁。生产环境必须通过rename-command把这些命令改名或直接禁用。改名时注意不要改成空字符串,否则命令会被彻底禁用,但也要留一个只有运维知道的复杂名字,防止自己都执行不了。
# redis.conf 示例 requirepass your-strong-password-here rename-command FLUSHALL "some_random_long_string_1" rename-command FLUSHDB "some_random_long_string_2" rename-command CONFIG "some_random_long_string_3" rename-command SHUTDOWN "some_random_long_string_4" rename-command DEBUG "" rename-command EVAL "some_random_long_string_5"
光改命令还不够,网络层的隔离才是兜底。Redis应当只监听内网地址,禁止bind 0.0.0.0。如果业务和Redis在同一台机器,直接bind 127.0.0.1最安全。如果跨机器访问,必须通过内网网卡IP绑定,并在防火墙或安全组里只放行特定来源IP。云服务器上尤其要注意,安全组规则比系统防火墙优先级更高,两边都要配置。很多人只改了redis.conf里的bind,结果安全组还是0.0.0.0/0,等于白改。
protected-mode这个参数经常被误解。它默认开启,只有在没有设置密码且没有绑定指定IP时才会拒绝外部连接。但一旦你设置了密码,protected-mode的拦截逻辑就不再生效,所以不能把它当成安全网。正确做法是:bind明确指定内网IP,requirepass设置强密码,protected-mode保持yes,三者配合使用。单独依赖任何一个都有漏洞。
Redis的ACL功能从6.0版本开始提供,这是比requirepass更细粒度的权限控制。你可以创建不同用户,给业务只读权限,给运维写权限,给监控账号只允许执行INFO和PING。这样即使某个业务账号泄露,攻击者也无法执行写操作或修改配置。ACL规则写在redis.conf里,也可以通过ACL SETUSER命令动态修改。建议生产环境至少创建两个账号:一个默认用户禁用或限制权限,一个管理员账号用强密码。
# ACL 示例 user default off user appuser on >appuser_password ~cache:* +get +set +del +exists +expire +ttl user admin on >admin_strong_password ~* +@all
数据持久化文件也是泄露重灾区。RDB和AOF文件里保存的是内存数据的二进制或文本快照,如果服务器被入侵,攻击者直接拷贝这些文件就能拿到全部缓存内容。所以持久化文件的目录权限必须收紧,只允许Redis运行用户读写。同时不要把Redis数据目录放在Web可访问的路径下。如果缓存里存了敏感信息,建议在应用层先加密再写入Redis,这样即使文件泄露,数据也不会直接暴露。
TLS加密传输在国内讨论得少,但如果你通过公网或跨机房访问Redis,明文传输意味着密码和数据都能被中间人抓包。Redis 6.0以上支持TLS,编译时需要加BUILD_TLS=yes,配置里指定证书和私钥路径。如果暂时无法启用TLS,至少用stunnel或spiped做一层加密隧道。内网环境如果信任度较高,可以暂缓,但公网访问必须加密,没有妥协余地。
慢查询日志和监控是安全防护的“眼睛”。攻击者执行KEYS *或者大量SCAN时,慢查询日志会记录下来。把slowlog-log-slower-than设置成10000微秒,slowlog-max-len设置成128或更大,定期检查有没有异常命令。同时监控Redis的连接数、内存使用率、命令执行频率,一旦出现陌生IP连接或QPS异常飙升,立即告警。很多入侵行为在数据被清空前是有预兆的,比如先执行INFO、CONFIG GET dir、CONFIG GET dbfilename等探测命令。
还有一个常被忽视的点:Redis的版本更新。老版本存在已知漏洞,比如4.x和5.x的某些版本存在远程代码执行风险。不要抱着“能用就不动”的心态,至少保持在大版本的最新小版本上。升级前在测试环境验证兼容性,尤其是持久化文件格式和客户端库的兼容情况。如果实在无法升级,就要通过禁用相关命令和网络隔离来缓解风险。
容器化部署Redis时,安全配置不能只写在镜像里。很多人用docker run启动Redis时忘记挂载配置文件,结果容器用的是默认配置,密码为空,绑定0.0.0.0。正确的做法是把redis.conf挂载进容器,或者用docker-compose明确指定command参数。K8s环境里用ConfigMap管理Redis配置,但要注意ConfigMap里的密码不要明文提交到Git仓库,可以用Secret挂载。
最后强调一点:安全是分层防御,不是单点加固。密码、ACL、命令重命名、网络隔离、TLS、文件权限、监控告警,每一层都在增加攻击成本。不要觉得“我们只是内部系统,不会有人攻击”,内部威胁和误操作同样致命。定期做一次Redis安全自查:检查requirepass是否设置、bind是否合理、高危命令是否禁用、ACL是否启用、持久化文件权限是否正确、慢查询日志里有没有异常命令。把这些检查项做成脚本,每次发版前跑一遍,比事后补救强得多。
