
你在生产环境里见过不设置密码的Redis吗我见过而且是在一场惨烈的故障里。当时一台低配服务器上跑着一个业务量不大的Redis实例开发图省事没配密码只做了内网IP绑定。结果某天下午这台服务器CPU飙到100%上去一看Redis里多了个可疑的key里面塞着一段下载脚本——公网扫描器正通过主从复制往机器里塞挖矿程序。最后只能杀进程、清数据、改配置、换IP折腾了一整晚。这件事给我的教训很直接Redis的默认安全模型假定“网络是可信的”一旦这个假定被打破密码就是最低限度的防线。不管你是单机、主从、哨兵还是集群把密码配好是所有Redis上生产的第一步。接下来我就围绕“Redis设置密码”这件事从最基本的requirepass讲到Redis 6的ACL用户体系再到客户端连接、密码轮换和主从/集群场景下的配合方式。无论你是刚装好Redis的入门用户还是正在维护一套集群的运维都能在这里找到可以直接照做的方案。下面先说清楚为什么Redis的密码不是可选项。1. Redis默认配置下的安全风险不设密码到底意味着什么1.1 默认状态下Redis的门是半掩着的先从结论说起。Redis 3.2之后的默认配置会开启protected-mode同时监听地址是127.0.0.1所以装完Redis不碰配置直接启动外部机器连不上表面上很安全。但protected-mode的机制比很多人以为的更细当它开启、实例没有配置密码、并且监听地址包含非回环地址时Redis会拒绝来自外部网络的连接并返回错误提示。这就像一个“默认拒绝外部”的开关。问题在于这个开关的优先级低于认证。一旦你在配置里加了requirepass相当于明确声明“本实例允许外部通过认证访问”protected-mode对外部连接的拦截就会让位给认证机制。很多团队是这么出事的装好Redis后随手bind 0.0.0.0没设密码发现外网连不上就以为很安全后来有人为了远程访问加了密码结果密码设置得太简单或者密码本身又被扫到了于是实例就暴露了。说白了protected-mode只是默认保护设置密码才是主动的安全声明。更麻烦的是扫描器。公网上有大量自动化脚本每时每刻都在扫描6379、6380这类默认端口。它们拿到开放端口后第一件事就是执行redis-cli -h ip ping这类无害命令看有没有返回PONG。一旦发现一个不需要密码的实例后续攻击链马上跟进写入crontab、通过主从复制写文件、用Lua脚本枚举数据、把库里的数据搬走再塞入勒索信息。如果Redis里有业务缓存最直接的损失是数据泄密如果Redis开启了持久化且能被写入攻击者还可能利用主从复制或其他特性在磁盘上写出恶意文件把数据服务器变成矿机甚至在部分场景下拿到执行权限。这些不是危言耸听安全公告里都能看到真实案例。1.2 哪些场景最容易出问题根据我这几年的运维经验下面这几类场景最常见开发/测试环境直接绑定0.0.0.0图省事不设密码内网另一台机器被攻破后横向移动Redis跟着遭殃。把Redis部署在云服务器上安全组规则写了0.0.0.0/0所有IP等于把端口全开给公网。用Docker启动Redis时没有做任何认证配置端口又映射到宿主机。公司内部公共Redis多个团队共用有人误执行FLUSHALL导致缓存全清。为了临时联调把Redis端口用frp或Nginx反代暴露到外网忘了加密码。这些场景只要碰到一个就有必要设置密码。可能有人会说“我们的Redis只在内网没啥风险”但内网横向渗透在真实攻击中非常常见尤其是跳板机失守的情况下内网每个开放端口都可能成为下一跳。密码虽然不能替代网络隔离但它能把“意外连接”变成“必须通过认证才能连接”这个门槛就是一层非常实用的兜底。1.3 设置密码能挡住什么、挡不住什么给Redis设置密码后能挡住以下几类问题公网扫描器和未授权访问脚本它们不会花时间猜一个强随机密码。内网误连有人开错端口、指错IP会被认证报错拦住而不是直接拿到数据或执行危险操作。误操作没有认证权限的普通人员无法直接执行FLUSHALL、CONFIG等危险命令。但密码挡不住的是合法用户误操作、应用代码里的弱密码被泄露、以及TLS缺失状态下流量被窃听导致密码泄露。所以密码是必要不充分条件后面我还会讲怎么配合ACL和网络策略一起用。2. requirepass配置方式配置文件、命令行与动态切换全走一遍2.1 最基础的做法在redis.conf里设置requirepass如果只用一句话回答“Redis怎么设置密码”那就是在redis.conf里加上一行requirepass YourStrongPassword2024然后启动时指定配置文件。如果是系统自带的Redisconf文件通常在/etc/redis/redis.conf或者安装目录下如果是源码编译一般是redis.conf。启动命令redis-server /etc/redis/redis.conf设置完成后用redis-cli连上去执行命令就会出现127.0.0.1:6379 keys * (error) NOAUTH Authentication required.这时候必须先认证redis-cli -p 6379 127.0.0.1:6379 auth YourStrongPassword2024 OK 127.0.0.1:6379 keys * (empty array)需要注意的坑requirepass在redis.conf里的顺序无所谓但要注意不要把好几份conf文件搞混。尤其用Docker部署时宿主机和容器里的conf文件路径经常不一样改错了配置等于白改。我自己就犯过一次在宿主机上改了redis.conf容器内启动时挂载的是另一个目录的conf结果改了半天还是连不上。2.2 命令行启动不写配置文件也能设置密码临时启动一个测试实例时可以不带配置文件直接通过参数传redis-server --requirepass mypass --port 6379这种方式适合临时验证排查但我不建议在生产环境用。原因很简单命令行参数会被进程列表看到ps aux会显示进程启动命令如果密码写在里面等于是把密码暴露给了所有能登录这台机器的用户。如果你只是临时测试又不想留痕可以用一个更稳妥的方法先启动不带密码的Redis实例然后通过redis-cli连进去执行CONFIG SET。这样密码只会出现在配置文件和Redis运行时内存里不会出现在进程参数里。2.3 动态修改不改配置文件的情况下重置密码Redis允许在运行时动态修改requirepass这在密码轮换场景下非常关键流程是这样# 先连接上实例 redis-cli -p 6379 # 执行过auth认证 auth oldpass # 修改密码 config set requirepass newpass # 让配置持久化到磁盘 config rewrite执行完config set requirepass newpass之后当前已认证的连接不会被踢掉但新连接的客户端必须使用newpass。这是Redis的一个独特行为很多第一次操作的人会愣一下为什么我改了密码自己还没断原因就是Redis对已认证连接保持信任不主动断开只有新连接才需要走新的认证流程。关于config rewrite需要多说一句它会把当前生效的配置写回redis.conf。如果你用config set临时改了密码却忘了config rewrite重启后Redis会回到旧密码这个问题我后面专门讲。还有一点很容易忽略config set requirepass本身是一条CONFIG命令在设置了requirepass之后未认证连接无法执行CONFIG命令会直接报NOAUTH。所以“用config set设密码”这个动作必须由一个已经知道当前密码的连接来完成。通俗地说你不能给一台完全未知密码的Redis设置新密码必须先用旧密码登录进去。2