Redis密码设置实战:从requirepass到主从集群认证避坑指南

Redis密码设置实战:从requirepass到主从集群认证避坑指南 先把丑话说在前面Redis 设置密码这个事看着简单但真到生产环境里翻车的人我见过太多了。不是忘了设就是设完主从同步断了再不就是改了密码之后应用连不上、运维脚本全部失效。我的建议是不管你是本地开发还是上云部署都老老实实把认证机制吃透再动手去配。这篇文章不会只教你敲一条requirepass我会把密码设置背后的默认行为、四种主流配置方式、客户端侧怎么适配、主从哨兵集群里的连带配置、以及我实际踩过的一堆坑全部讲清楚。内容偏运维实践读完你至少能独立完成一套带认证的 Redis 部署不会再被NOAUTH这类报错卡住。1. Redis 默认不带密码的真实原因以及什么时候必须立刻补上很多人第一次装完 Redisredis-cli ping直接返回PONG第一反应是“好家伙这么快就通了”。速度确实快但这不代表配置就完整了恰恰相反它是在裸奔。1.1 默认配置里那三个和安全相关的“隐形开关”Redis 默认是允许无密码访问的但这不等于 Redis 官方没想过安全问题。它其实给了三道默认防护只是大部分新手没注意到bind 127.0.0.1 -::1默认只监听本机回环地址外部 IP 访问不了protected-mode yes保护模式开启。在没有配置 bind 到外部地址、也没有设置密码的情况下Redis 会拒绝来自非本机地址的连接requirepass默认是空的也就是说认证功能完全没启用。这三者叠加的逻辑是你在本机开发调试时可以直接免密访问体验很顺。但只要你想让别的机器连上来就必须手动决定是“放开 bind 并关闭保护模式”还是“设置密码”没有第三条路。很多线上事故恰恰是因为有人把bind注释掉、让 Redis 监听所有网卡然后又没设置密码相当于亲手把大门打开了。1.2 不加密码在真实环境里到底会发生什么我可以直接告诉你结果把 Redis 跑在公网服务器上且端口暴露快的话几分钟内就会被扫描器发现。扫描器不会跟你客气先是INFO、CONFIG GET这类命令探测接着可能就是FLUSHALL清空数据或者写入一些恶意调度任务。对企业应用来说缓存被清空往往比想象中更疼——缓存失效后流量直接打到数据库搞出一次缓存雪崩数据库压力瞬间爆表半天缓不过来。更隐蔽的风险是数据被篡改。Redis 里如果存了会话、验证码、临时授权信息这类业务数据攻击者改一个 key 就能绕过某些业务逻辑。内网部署也一样不是说公司内网就绝对安全一个端口扫描脚本撒下去内网照样有被扫到的可能。所以只要 Redis 要监听非本机地址就必须把密码设置这件事放进上线清单。1.3 哪些场景必须立刻设置密码根据我的经验下面这些场景不要犹豫第一时间设密码云服务器上部署的 Redis尤其是绑定了公网 IP 的任何使用 Docker 端口映射的 Redis比如-p 6379:6379公司内网多台机器需要访问的 Redis生产环境的 Redis不管前面有没有防火墙云数据库 Redis 实例控制台创建时就要配置访问密码。本地学习、单个开发机自己玩玩可以暂时不设。但我个人的建议是哪怕只是本机用也顺手设一个养成肌肉记忆省得哪天真上了生产环境还给忘了。2. 四种主流设置方式从配置文件到 Docker选哪个取决于你的场景Redis 设置密码有好几条路没有哪条是绝对最优关键看你的部署方式和是否允许重启。2.1 改 redis.conf 文件最稳妥、最推荐的方式这种方式适合所有用配置文件启动的 Redis。步骤非常简单找到 Redis 的配置文件通常位于/etc/redis/redis.conf源码安装的话一般在安装目录下搜索requirepass找到默认被注释掉的那行# requirepass foobared取消注释改成你自己的密码比如requirepass YourStrongPssw0rd保存文件重启 Redis 服务。重启之后立刻验证一下效果redis-cli ping # 输出: (error) NOAUTH Authentication required. redis-cli -a YourStrongPssw0rd ping # 输出: PONG这里我要强调一个非常容易被忽略的细节requirepass的值支持任意字符串但如果你在配置文件里写了一个带空格的密码解析行为会比较怪报错也不好排查。所以我建议生成密码时就避开空格尽量用A-Za-z0-9加上少量安全符号的组合。想要省心一点可以直接用系统命令生成一段十六进制密码openssl rand -hex 32十六进制密码只包含数字和a-f不会碰到 shell 特殊字符配置文件里也不用加引号是我比较常用的一种稳妥方案。2.2 CONFIG SET 命令不停机热生效但要记住它随时会丢如果 Redis 正在线上跑着不能随便重启你可以用CONFIG SET动态修改redis-cli CONFIG SET requirepass YourStrongPssw0rd执行之后新的连接就必须用这个密码认证。这个方式的优势是即时生效、不用重启服务适合在做配置变更时先验证效果确认没问题再落盘。但这里有个大坑CONFIG SET改的是运行内存里的配置不会自动写回文件。如果你改完密码后直接重启 Redis密码就丢了回到无密码状态。想让配置持久化还需要执行redis-cli CONFIG REWRITE这条命令会把当前生效的配置重写回redis.conf。注意CONFIG REWRITE是否能正常工作取决于启动时指定的配置文件路径如果你是用默认配置启动、没有显式指定配置文件它可能会报错或者写不进去。我在生产环境里见过因为这个问题导致密码“神秘消失”的情况排查到最后才发现配置文件压根没被加载过。2.3 Docker 容器部署两种姿势别再傻傻进容器改配置了Docker 部署 Redis 时最常见的一个错误是进入容器内部去改配置文件结果容器一删重建配置全没了。正确做法是让容器启动时就带上认证参数。第一种方式直接通过命令行参数传入docker run -d --name redis-auth \ -p 6379:6379 \ redis:7.2 \ redis-server --requirepass YourStrongPssw0rd --appendonly yes第二种方式挂载自定义配置文件docker run -d --name redis-auth \ -p 6379:6379 \ -v /path/to/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7.2 \ redis-server /usr/local/etc/redis/redis.conf如果你用的是 Docker Composecommand数组写法也差不多services: redis: image: redis:7.2 command: [redis-server, --requirepass, YourStrongPssw0rd, --appendonly, yes] ports: - 6379:6379我的一个习惯是只要能挂载配置文件就尽量挂载配置文件而不是堆一长串命令行参数。原因很简单配置文件可注释、可维护后来的人看git diff也知道改了哪里命令行参数挂在那时间一长没人说得清当初为什么这么写。2.4 云数据库 Redis别在控制台外面瞎折腾如果你用的是云厂商提供的 Redis 实例情况又不一样。云数据库通常不开放CONFIG命令你想通过客户端执行CONFIG SET requirepass大概率会收到ERR unknown command之类的拒绝。正确做法是在云厂商控制台找“重置密码”或“修改密码”入口跟随提示操作。有些云 Redis 的账号体系比较特殊连接时除了密码还需要填写用户名而且用户名不一定叫default可能是实例 ID。这个细节一定别忽略不然你怎么试密码都是AUTH失败。另外部分云 Redis 在控制台修改密码后旧的连接可能会保持一段时间如果你改了密码后业务突然报错检查一下是不是连接池里还留着旧连接。3. 设完密码之后的客户端连接与实际代码适配密码设置只是服务端的事真正的考验在客户端。我见过很多人在服务器上敲完CONFIG SET requirepass然后高高兴兴跑回代码里结果应用啪啪报错一看日志全是认证失败。3.1 redis-cli 的认证细节以及最常见的 NOAUTH 报错未认证时在 redis-cli 里敲任何命令Redis 都会回一句(error) NOAUTH Authentication required.这句话翻译过来就是“你没认证别想干活”。解决办法是在连接后执行认证命令redis-cli 127.0.0.1:6379 AUTH YourStrongPssw0rd OK也可以一步到位redis-cli -a YourStrongPssw0rd ping不过我要提醒你-a方式把密码明文放在了命令行里会出现在 shell history 和进程列表中生产环境的脚本里尽量少用。更稳妥的做法是使用环境变量export REDISCLI_AUTHYourStrongPssw0rd redis-cli ping需要留意REDISCLI_AUTH是 redis-cli 自身的环境变量不是 Redis 服务端的配置它只对客户端生效不影响服务端行为。还有一个新手很容易误解的报错(error) ERR Client sent AUTH, but no password is set这句话的意思是服务端根本没设密码但客户端主动发了 AUTH 命令。如果你检查配置文件发现requirepass确实没启用那就别发 AUTH如果你认为自己设了密码那就要回头查配置是否真的生效了。3.2 各语言客户端的密码配置怎么写不管用哪种语言核心就一件事连接对象里把password或auth参数传对。我举几个常见的Python 的 redis-pyimport redis client redis.Redis( host127.0.0.1, port6379, passwordYourStrongPssw0rd, decode_responsesTrue ) print(client.ping()) # TrueJava 的 JedisJedis jedis new Jedis(127.0.0.1, 6379); jedis.auth(YourStrongPssw0rd); System.out.println(jedis.ping());如果你用 Spring Boot则是在application.yml里配置spring: data: redis: host: 127.0.0.1 port: 6379 password: YourStrongPssw0rdGo 的 go-redisclient : redis.NewClient(redis.Options{ Addr: 127.0.0.1:6379, Password: YourStrongPssw0rd, })Node.js 的 ioredisconst Redis require(ioredis); const client new Redis({ host: 127.0.0.1, port: 6379, password: YourStrongPssw0rd, });这些代码看着简单但有一个共同的大坑连接池。很多客户端默认会维护一批长连接如果你改了密码旧连接已经通过认证可能在短时间内还能继续用但新建立的连接会使用新密码万一应用里连接池没有重建很快就会出现“一部分请求正常、一部分请求报 NOAUTH”的诡异现象。正确操作是改完密码后重启应用或者重置连接池别指望它自动感知。3.3 图形化连接工具怎么填认证信息常用的 Redis 桌面客户端比如 Redis Desktop Manager、Another Redis Desktop Manager界面上都会有 Password 或 Auth 字段。连接前先把服务地址、端口、密码填好然后在“测试连接”里下意识敲一下 ping确认返回 PONG 再保存。有一点容易被忽略如果你连的是内网 Redis而本机无法直接访问很多图形工具支持 SSH 隧道方式连接这时候密码填的是 Redis 的密码SSH 的认证信息另填两码事不要混在一起。3.4 应用重启后还是连不上按这个顺序查如果应用重启后依然报认证失败我一般按下面的顺序排查确认服务端密码确实生效redis-cli -a 密码 ping确认客户端配置文件没有残留旧密码或占位符确认密码里没有特殊字符被配置文件、环境变量或命令行二次解析掉了确认 Redis 6 以上版本是否启用了 ACLACL 的默认用户权限是否覆盖了requirepass。重点说第四点因为这是 Redis 6 之后非常容易埋雷的地方。如果你启用了 ACL并且把default用户设置成了nopass那即使你配了requirepass默认用户依然可以免密连接。原因是requirepass本质上是给default用户设密码ACL 的优先级更高一旦 ACL 里声明了nopassrequirepass就形同虚设。出现这种配置错位时光看CONFIG GET requirepass是查不出问题的必须用ACL LIST或ACL GETUSER default看用户的真正认证策略。4. 主从、哨兵、集群里的密码策略不是设一份就完事单机 Redis 设置密码很简单但一旦涉及到主从复制、哨兵和集群很多人就栽了。原因是每台 Redis 都有两份“密码”一份是给客户端用的另一份是给节点间复制链路用的。4.1 masterauth 字段从库连主库的钥匙当你给主库设置requirepass后从库通过replicaof masterip masterport发起复制时默认是不会带密码的。于是主库收到从库的连接请求后直接拒绝认证从库日志里会反复出现类似MASTER IP:PORT replied: error:-NOAUTH Authentication required.复制链路根本建立不起来。解决办法是在从库配置里加上masterauth YourStrongPssw0rd需要特别注意的是masterauth和requirepass是两回事requirepass管的是“客户端访问本节点”masterauth管的是“本节点作为从库去连接主库时用哪个密码”。所以哪怕主从两边的requirepass一致从库也必须显式配置masterauth否则照样复制失败。用命令动态调整的话可以这样redis-cli CONFIG SET masterauth YourStrongPssw0rd如果是 Redis 6 以上版本配合 ACL 使用还有一个masteruser字段用来指定复制链路使用的用户名一般场景用不上但如果你搞了多用户 ACL就要一并检查。4.2 哨兵模式密码对齐决定故障转移靠不靠谱哨兵模式下事情多了一层。哨兵本身要连接主库和从库执行INFO、SUBSCRIBE等命令所以它也需要知道密码。在sentinel.conf里需要这样配置sentinel auth-pass mymaster YourStrongPssw0rd这里的mymaster是你定义的监控主库名必须和sentinel monitor mymaster 127.0.0.1 6379 2里的名字一致。我遇到过一个很经典的问题哨兵配置了auth-pass但某个从库的密码忘了设置或者设得跟主库不一样。平时看起来一切正常一旦主库挂掉哨兵发起故障转移把那个从库提升为新主库结果哨兵和新主库之间认证不上整个集群立刻进入奇怪的状态。所以哨兵场景下我建议主从库统一使用同一个requirepass主从库都配置相同的masterauth哨兵统一配置sentinel auth-pass改密码时所有节点的配置同步更新不要只改主库。4.3 集群模式所有节点必须执行同一套认证策略Redis Cluster 的模式下每个节点既是主又是从节点间会有 gossip 通信和数据迁移逻辑比哨兵更复杂。配置密码时最简单的策略是让所有节点使用相同的requirepass和masterauth避免出现“这个节点能连、那个节点不能连”的分裂状态。用命令逐个节点设置也可以但我在生产上不推荐手动一个个来因为很容易漏。更可靠的做法是把配置文件模板统一分发所有节点用同一套模板启动密码、masterauth、cluster-enabled yes这些值保持一致。集群节点的认证配置不一致时表现往往是集群状态正常但不稳定数据迁移、副本同步都会随机报错排查起来非常费力。另外还要提醒一句集群节点的客户端连接需要认证但集群总线端口默认 16379上的节点间通信靠的是集群协议不是 AUTH 机制。所以节点间的网络访问要放在内网或受信任的网络环境里不要靠 Redis 的密码去保护集群总线。4.4 Docker Compose 编排一个带密码的主从示例直接给一个可以抄走的docker-compose.ymlservices: redis-master: image: redis:7.2 command: [ redis-server, --requirepass, masterpass, --appendonly, yes ] ports: - 6379:6379 redis-slave: image: redis:7.2 command: [ redis-server, --replicaof, redis-master, 6379, --masterauth, masterpass, --requirepass, masterpass ] depends_on: - redis-master这个例子里从库既配置了masterauth用来连主库又配置了requirepass用来限制外部客户端直接访问从库。后面这一点经常有人漏掉——只配masterauth不配requirepass从库等于对全网裸奔任何人连上从库都能读数据。启动之后进入从库容器看一眼复制状态docker exec -it slave-container redis-cli -a masterpass info replication重点关注master_link_status:up如果看到down基本就是密码不对或者主库连接有问题。5. 设完密码后最容易踩的几个坑全是实际案例配置过程讲完了下面这些坑是我在实际运维和帮别人排查时真实遇到过的。每一个都不算高深但都很容易让人心态爆炸。5.1 CONFIG REWRITE 把密码写进文件但文件权限没管好前面提到过CONFIG REWRITE会把运行中的配置写回文件。这里有一个安全细节密码会明文保存在redis.conf里。如果文件权限是默认的 644那么系统上任何一个用户都能cat这个文件密码等于白设。我自己的习惯是Redis 配置文件所在目录权限设置为 750配置文件本身设置为 640属主设为 Redis 运行用户。不同发行版细节稍有差异但原则上不要让普通用户有读取权限。尤其是多用户共用的服务器这个细节务必检查。5.2 密码里的特殊字符被 shell 悄悄“吃掉了”这是命令行操作里非常经典的问题。假设你的密码是Pss$word执行redis-cli -a Pss$word pingshell 会先把$word当成变量解析实际传给 redis-cli 的密码可能变成了Pss于是收到(error) ERR invalid password正确做法是把密码用单引号包起来redis-cli -a Pss$word ping但如果密码里本身含有单引号那又得换双引号或者做转义很容易绕晕。所以我强烈建议生成密码时只使用字母、数字和!、、#、%、*、-、_、这类在大多数场景下不需要转义的字符或者干脆用openssl rand -hex 32生成纯十六进制密码。简化密码字符集比临时去研究 shell 转义规则靠谱得多。5.3 修改密码后旧连接还在导致你以为密码没生效我之前遇到过这样的场景运维改了 Redis 密码但应用没有重启。诡异的是应用居然还是能正常读写于是一堆人开始怀疑是不是改密码的命令没生效。后来才发现应用连接池里的旧连接早就通过了 AUTHRedis 在修改requirepass后并不会主动掐断已经认证过的连接这些连接一直保持着“合法身份”只有新连接才会被要求使用新密码。这个行为的直接后果是改密码后你会看到一个“新旧密码并行可用”的过渡期过渡期长度取决于连接池多久会销毁旧连接。如果你想尽快让旧密码失效唯一稳妥的办法是重启所有客户端应用或者让连接池重置不要指望 Redis 一个命令就能让所有旧连接原地失效。5.4 密码只是第一道门别把安全希望全押在 requirepass 上设置密码确实能挡住大部分裸连扫描但如果你把 Redis 端口完全暴露到公网即使有密码也会面临持续的口令爆破风险。我见过一台 Redis 的日志里一个小时内有上千次 AUTH 失败记录全是扫描器在猜密码。所以我还有几条补充建议密码长度至少在 16 位以上最好 32 位别用123456这种用 Redis 6 的 ACL 做更细粒度的权限控制给不同业务分配不同用户而不是所有人共用一个超级密码监听地址尽量用bind限制到内网 IP用防火墙限制 6379 端口的来源只允许业务机器访问如果条件允许换一个非默认端口虽然不能防扫描但能减少大量自动化攻击流量。ACL 的简单示例是这样redis-cli -a YourStrongPssw0rd ACL SETUSER appuser on apppass ~app:* read get把权限限制在只能访问app:*前缀的 key、只允许读命令比一个全量超级密码要安全得多。当然ACL 本身就够写一篇文章这里不展开但你应该知道requirepass不是认证的终点。6. 一套可以直接照做的操作清单和问题排查速查表最后这部分是给已经看完所有原理、准备动手配置的人准备的。你可以把它当成一份 checklist照着做基本不会漏。6.1 从零开始配置密码的八步操作用openssl rand -hex 32生成一个强密码修改redis.conf中的requirepass或者在 docker 启动命令中追加--requirepass如果是 Docker 容器确认端口映射没有同时把配置目录挂载得乱七八糟重启 Redis然后用redis-cli ping确认未认证时被拒绝用redis-cli -a 密码 ping确认认证后返回PONG如果存在主从、哨兵或集群同步更新masterauth、sentinel auth-pass或所有节点的密码配置更新客户端应用的连接配置修改密码后重启应用或重置连接池更新运维文档、监控脚本、告警平台里的密码信息。6.2 常用验证命令与预期输出操作预期结果redis-cli ping(error) NOAUTH Authentication required.redis-cli -a 密码 pingPONGredis-cli -a 密码 CONFIG GET requirepassrequirepass后跟密码原文生产环境慎用redis-cli -a 密码 AUTH wrongpass(error) ERR invalid passwordredis-cli -a 密码 ACL LIST返回用户信息能看到 default 用户的认证状态redis-cli -a 密码 INFO replicationmaster_link_status:up表示主从复制正常这里特别提醒一下CONFIG GET requirepass会把明文密码打印出来所以在生产环境或者有人共享屏幕的时候不要随便执行防止密码泄露。6.3 常见异常与处理对照报错信息可能原因处理方式NOAUTH Authentication required.客户端未认证或密码未填写配置密码后执行AUTHERR Client sent AUTH, but no password is set服务端没设密码客户端却发了 AUTH移除客户端认证配置或在服务端加密码ERR invalid password密码错误检查密码拼接、特殊字符和文件编码ERR unknown command CONFIG云数据库或权限受限用户禁用了 CONFIG到云控制台修改密码-DENIED Redis is running in protected mode保护模式下无密码且监听外部地址设置密码或调整 bind 和 protected-modeMASTER auth failed从库masterauth错误修改从库masterauth并重启复制链路NOAUTH出现在哨兵日志哨兵auth-pass未配置或错误修改sentinel.conf中的 auth-pass我个人在实际操作里还有一个习惯每次改完 Redis 密码都会专门留一个窗口时间观察日志重点看有没有反复的 AUTH 失败确认没有其他老服务还在用旧密码硬连。因为很多历史遗留服务不会主动报错而是默默地在重试日志里刷一堆NOAUTH你以为没事其实它一直没连上。如果你用的是 systemd 管理的 Redis 服务重启前记得用CONFIG GET requirepass确认当前生效的密码后再动手顺序不要反了。先把配置文件改好再重启不然可能出现“重启后配置没加载密码反而没了”的尴尬局面。最后再分享一个我个人的习惯即使开发环境只有我一个人用我也会设置一个随机生成的密码并把它放在本机的密码管理器里。因为开发机往往装了各种环境变量和脚本你不知道什么时候一个不起眼的小程序就会去连 6379 端口。设了密码之后至少能挡住大部分意外和误操作。密码这个东西线上不能省线下也别嫌麻烦。