ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Redis设置密码完全指南:从requirepass到主从哨兵集群

Redis设置密码完全指南:从requirepass到主从哨兵集群 1. 为什么Redis必须设置密码这是踩过坑之后的真心话先说一个我自己经历过的场景某次为了方便本地联调把开发环境里的Redis bind设成了0.0.0.0然后仗着“内网没关系”就没设密码。结果某天早上发现6379端口被捅数据库里的键值全被换成了一串比特币地址。虽然那只是个缓存服务数据没了能重建但排查过程极其痛苦得一遍遍回捞日志、清依赖最后还得跟运维解释为什么生产配置里藏着这么个裸奔实例。从那以后凡是部署在非本机回环地址上的Redis我第一件事就是先把requirepass写好再谈别的。其实Redis默认配置里也有保护机制只要没显式配置bind和requirepass它就是只允许127.0.0.1访问的而且开启protected-mode之后只能本机连接。但问题在于很多人拿到Redis后第一件事就是注释掉bind 127.0.0.1改成0.0.0.0为的是让局域网/远程能访问但又忽略了密码设置——这一下就把默认保护全部绕过了。Redis本身是一款高性能的键值存储常用于缓存、会话管理、分布式锁等等场景一旦暴露在不受信网络里等于给恶意访问者递了一把钥匙能通过FLUSHALL直接把缓存清空甚至利用高版本的功能去读主机文件非常危险。所以这篇文章就是围绕“Redis设置密码”这件事把配置文件写法、命令行的动态更新方式、Docker容器里的设置方法、主从复制/哨兵模式下的密码联动以及客户端连接时容易踩的坑全部过一遍。不管你是刚装完Redis还没头绪的新手还是已经部署了一套但密码配得不够完善的老手下面的内容都值得从头到尾看一遍。我自己从裸奔到规范配置中间踩过的坑能帮你少走不少弯路。提示如果你只是在单机本地做开发Redis可以只监听127.0.0.1且不设密码但只要你把地址暴露给局域网或者开了Docker端口映射就必须立刻把密码加上。2. 密码配置前的准备工作先搞懂这几个概念后面才不会乱2.1 requirepass、masterauth、acl这些参数到底是干什么的Redis的密码体系不是只有“一个requirepass”这么简单。先说最先接触的requirepass它设置的是Redis服务端对普通客户端的访问密码。用户连接后第一次执行命令前必须先通过AUTH验证否则会报NOAUTH Authentication required。这是最经典也最好用的一种密码设置方式一视同仁所有客户端共用一个密码。但如果你是做主从复制或者哨兵集群的光配requirepass还不够。从节点需要向主节点发起同步从节点本身也要被客户端连接如果只设了masterrequirepass从节点的配置里还要额外指定masterauth用来让从节点在连接主节点时自动完成身份认证。这里很多人会忽略结果明明两边都设置了同样的requirepass从节点却一直报MASTER auth failed。原因就是masterauth没有配。另外Redis 6.0之后引入了完整的ACLAccess Control List体系acl相关命令可以做到更细粒度的权限控制比如给不同业务线分配不同用户名和密码限制能访问的keys和能执行的命令。虽然ACL更强大但对于大多数中小项目来说用requirepass加上合理防火墙策略已经够用了。这篇文章以requirepass为核心后面也会提一句主从场景下masterauth怎么联动。2.2 先找到你的Redis配置文件别用错了目录在动手之前第一步是确认Redis的配置文件在哪里。一般Linux环境通过apt或yum安装的Redis配置文件在/etc/redis/redis.conf从官网下载源码编译安装的默认在安装目录下比如/usr/local/redis/redis.conf。Windows下的Redis没有官方版本通常用的是微软或厂商移植的版本配置文件名多为redis.windows.conf或redis.windows-service.conf。我第一次没看准配置文件直接用redis-server启动发现设置死活不生效后来才发现自己改的是redis.conf但实际启动时用的是redis.windows.conf文件都找错了。所以记住一个原则启动的时候尽量显式指定配置文件路径例如redis-server /path/to/redis.conf这样才确定自己改的是不是真正生效的那份配置。可以先用redis-cli info server看下config_file字段或者直接执行redis-cli config get dir它返回的是配置文件所在目录方便定位。实操心得修改配置文件之前先用命令redis-cli CONFIG GET requirepass看一下当前生效的密码是什么避免误以为没配过结果手一滑覆盖了原有规则。3. 三种最常用的Redis设置密码方式场景各不相同3.1 方式一直接改redis.conf重启后永久生效先说最正规的方式。打开Redis配置文件找到# requirepass foobared这一段把注释去掉改成你自己的密码。比如# 将这一行取消注释并修改 requirepass yourStrongPassword123改完之后保存重启Redis进程。注意重启方式要看你的Redis是怎么运行的。如果是systemd管理的服务用systemctl restart redis如果是直接用redis-server启动的先CtrlC停掉再重新启动。重启之后用客户端连接不带密码直接执行命令会报127.0.0.1:6379 get username (error) NOAUTH Authentication required.需要先执行auth yourStrongPassword123然后再操作。这个方案的好处是永久生效不管进程重启多少次都有效。缺点是必须重启Redis如果是生产环境且缓存里有大量需要持久化的数据就会有一小段不可用窗口。所以我一般会在业务低峰期操作或者先用下面第二种方式动态修改等确认没问题再写回配置文件。3.2 方式二用CONFIG SET动态修改不用重启就能临时顶上去如果你不想立刻重启Redis或者只是想在线上临时改个密码应急可以直接在命令行里执行redis-cli -p 6379 127.0.0.1:6379 CONFIG SET requirepass newPasswordForNow OK执行这条命令后新密码会立刻生效不用重启。客户端重新连接时就要用新密码了。但这里有个坑CONFIG SET只是内存中的临时修改Redis重启之后又会恢复到配置文件里的旧值或者恢复为无密码状态。所以动态修改只适合临时应急。如果你确认这个密码要长期使用建议随后再执行CONFIG REWRITE把当前配置持久化到配置文件里127.0.0.1:6379 CONFIG REWRITE OK这个命令会把Redis内存中生效的配置写回配置文件前提是Redis配置文件路径可得且Redis对它有写权限。有些容器环境运行用户权限不足会报Rewriting config file: Permission denied需要先确认权限问题。注意CONFIG SET设置密码的瞬间当前连接不会被强制断开但你下一次执行命令时会发现居然还能执行这是Redis为了兼容性做的处理。不过新建连接必须用新密码否则认证不通过。3.3 方式三Docker容器里的Redis设密码别在容器里瞎折腾现在很多人的Redis都装在Docker容器里尤其是配合Kubesphere、Kubernetes这类编排平台跑的时候Redis通常作为一个Pod服务存在。使用Docker启动Redis镜像时最推荐的做法是把密码作为命令行参数直接传进去而不是进容器里面改配置。例如用redis:7.0镜像启动一个带密码的容器可以这样docker run -d --name redis-auth \ -p 6379:6379 \ -v /data/redis:/data \ redis:7.0 --requirepass yourStrongPassword123注意这里的--requirepass是传给Redis服务端的启动参数不是Docker的容器参数。它会覆盖镜像内的默认配置作为Redis进程启动时读取的命令行选项。启动后验证一下docker exec -it redis-auth redis-cli # 连接后执行 auth 127.0.0.1:6379 auth yourStrongPassword123 OK如果你有自定义的配置文件建议通过挂载方式带入容器例如docker run -d \ -v /myconf/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7.0 redis-server /usr/local/etc/redis/redis.conf这时候密码就写在宿主机上的/myconf/redis.conf里了容器内只是引用。不要在容器里手动改配置文件再commit镜像那是最差实践——临时性修改极易丢失而且镜像会越积越臃肿。4. 客户端连接时的那些坑密码设好了连不上才是真崩溃4.1 redis-cli里如何带密码连接别漏了空格和引号设置完密码之后最基础的就是命令行连接。两个常见写法一个是先连接再认证redis-cli -h 192.168.1.100 -p 6379 192.168.1.100:6379 AUTH yourPassword OK另一个是直接在连接时带上-a参数redis-cli -h 192.168.1.100 -p 6379 -a yourPassword ping PONG但这种写法有个安全风险命令参数会出现在进程列表里别人通过ps工具能看到完整密码。所以对生产环境我更推荐你先登录然后执行AUTH或者使用交互式方式。在脚本中如果必须用-a可以考虑通过环境变量传参但至少不要写在明文脚本里长期保存。另外如果你的密码里包含特殊字符比如#、、!、空格那么直接命令行里写-a my#password要注意单引号转义避免被shell误解。最保险的做法还是设置一些无特殊字符的密码省得各种客户端里配置起来出一堆问题。4.2 RedisDesktopManager / Another Redis Desktop Manager连接时Connection参数该怎么填可视化客户端现在用得最多的是RDMRedisDesktopManager和Another Redis Desktop Manager连接界面主要有Host、Port、Password几个字段。填的时候注意密码对应的是Password如果有ACL用户还要在User字段填用户名默认是default。很多人会在这里把密码填成AUTH xxx或者把整个命令填进去结果认证永远失败。我第一次用RDM连接的时候填了Host、PortPassword框里一旦填错直接被拒绝其实只要密码正确默认用户就叫default不需要再额外填用户名。连接成功后可以点击CLI标签页执行命令验证是否成功。实操心得RDM连接时如果提示WRONGPASS invalid username-password pair八成是密码打错了或者没注意到密码前后有空格。少数情况是Redis的ACL配置中把default用户的密码改了这时候需要填对用户名和密码不是只填密码能蒙混过关的。4.3 Python、Spring Boot连接Redis时的密码配置方式Python连接Redis标准做法是用redis-py库import redis r redis.Redis( host192.168.1.100, port6379, passwordyourStrongPassword123, decode_responsesTrue ) r.set(hello, world) print(r.get(hello))如果使用连接池则把密码参数放到连接池初始化时pool redis.ConnectionPool( host192.168.1.100, port6379, passwordyourStrongPassword123, db0 ) r redis.Redis(connection_poolpool)Java Spring Boot中使用Redis也很常见通常在application.yml或application.properties里直接指定spring: redis: host: 192.168.1.100 port: 6379 password: yourStrongPassword123 timeout: 3000ms如果Redis没有设密码这个password字段可以不写一旦设了密码就必须同步修改这里否则应用启动时会报Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: NOAUTH Authentication required。这里有个容易踩的坑如果你在Spring Cloud Config中或者K8s ConfigMap里统一管理配置改完Redis密码后一定要记得去更新配置中心里的那一份否则服务重启后用的是旧密码直接连不上。5. 主从复制、哨兵、集群模式下密码配置还会“传染”5.1 主从复制从库需要配masterauth否则复制链路直接断掉如果Redis以主从模式运行主库开启了requirepass从库必须配置masterauth否则从库连接主库执行PSYNC时会被拒绝。具体报错信息会在Redis日志里出现MASTER aborted replication with an error: NOAUTH Authentication required.或者1:M 01 Jan 2024 00:00:00.000 * MASTER - REPLICA sync started 1:M 01 Jan 2024 00:00:00.000 * Non blocking connect for SYNC fired the event. 1:M 01 Jan 2024 00:00:00.000 * Master replied to PING, replication can continue...然后紧接着就是认证失败。解决方式是在从库的配置文件里加上replicaof 主库IP 主库端口 masterauth 主库认证密码如果从库也配置了requirepass那是给连接从库的客户端用的跟复制链路无关。这个区分一定要搞清楚requirepass管客户端masterauth管主从之间。很多人在从库上设置requirepass后忽略了masterauth导致复制断开。5.2 哨兵Sentinel别忘在哨兵配置里指定auth-pass哨兵模式下哨兵本身要连接到主从节点来监控状态所以也要能通过认证。在sentinel.conf里除了标准的监控配置还需要使用sentinel auth-pass指定Redis的密码sentinel monitor mymaster 192.168.1.100 6379 2 sentinel auth-pass mymaster yourStrongPassword123这个masterauth的值必须跟主从节点上的requirepass保持一致。如果哨兵监控的节点有不同密码很少见分别指定也行但最好保持一致以减少维护成本。还要注意哨兵在故障切换后会把从节点提升为主节点这个过程如果从节点没有设置masterauth新的主节点可能又变成无密码模式导致复制和客户端连接全部出问题。所以配置主从密码时最好所有节点统一处理。5.3 集群模式每个节点都要设密码客户端需要统一配置Redis Cluster模式更讲究每个节点包括主节点和从节点都需要在配置文件中设置相同的requirepass和masterauth这样集群内部节点互相通信、迁移槽位时才能通过认证。如果集群中某个节点忘了设置会发现集群状态为failcluster nodes里某些节点标记为fail?检查日志全是认证异常。实际操作中我一般会写好一个统一配置片段批量分发到每个节点requirepass chongfuPassw0rd! masterauth chongfuPassw0rd!密码相同的情况下集群通信不会有额外压力。如果密码不同,redis-cli --cluster fix会让你在修复过程中输多次密码非常麻烦。所以集群场景的密码策略一定是“统一、固定、少改”。6. 常见问题与排查技巧实录这些情况我都遇到过6.1 设置完密码后远程客户端还是连不上这个现象很常见。服务端设置了密码并且bind 0.0.0.0也配了但远程客户端连接时要么直接超时要么报Connection refused。先排除防火墙和云安全组有没有放行6379端口然后查看Redis当前绑定的地址是不是只有127.0.0.1用命令redis-cli -a yourPassword config get bind返回127.0.0.1 -::1说明Redis根本没监听外部地址。这是很多新手容易踩的坑光加密码没改bind等于对外不可达。把bind改成0.0.0.0或者指定你的内网地址然后重启。还有一种情况是protected-mode yes导致的。即使你没有配置requirepass只要bind的不是127.0.0.1或者设置了密码protected-mode就会拒绝来自非本机的连接。所以如果你的Redis实例需要远程访问要么设密码要么把protected-mode设为no但强烈推荐的做法是设密码别关保护。6.2 明明密码正确的却提示WRONGPASS / invalid password先看用户名。Redis 6以后的ACL默认用户名是default如果你在可视化工具里填了自定义用户名很可能就不是默认用户。如果自定义ACL用户没配好密码对也会报错。再检查密码是否被shell、配置文件转义了。例如requirepass abc$123在shell中执行CONFIG SET时如果没加引号$123会被当成shell变量替换。这时候我们看到的密码根本不是实际密码看起来像密码正确但实际可能被改过了。最好用单引号包裹再执行。如果是通过环境变量或配置文件引入的密码尤其要留意末尾换行符\n这在很多部署脚本里会莫名被附加进密码中导致客户端看起来密码没错就是报错。排查方式是在Redis里执行CONFIG GET requirepass直接看服务端存储的密码值和客户端配置的做对比。实操心得我曾经排查过一个线上问题应用程序服务一直重连不上Redis结果发现是运维在K8s ConfigMap里写密码时YAML自动在末尾加了个空格导致密码变成“123456 ”。这种问题靠肉眼看配置根本发现不了一定得用三引号包裹或者严格检查。6.3 忘记Redis密码了紧急恢复怎么做先说一个应急操作如果Redis当前没有开启持久化或者你确认可以接受丢少量数据可以直接修改配置文件重启Redis这是一个简单的办法。但如果Redis已经在跑且你不想丢内存数据可以临时绕过密码验证吗除了重启并用--requirepass参数重新设置外没有更优雅的办法。因为AUTH是Redis核心认证逻辑无法在不重启的情况下绕过去。实际操作中我常用的恢复步骤先看进程是怎么启动的找到配置文件路径如果是systemd管理查/etc/systemd/system/redis.service里的ExecStart。停掉Redis进程systemctl stop redis或kill对应PID。编辑配置文件去掉requirepass行或改成已知密码。再启动Redis恢复服务。登录后立刻用CONFIG SET requirepass newPassword设置新密码再执行CONFIG REWRITE写回。这种方式的前提是你有操作系统权限能改配置文件。真到了那种Docker容器内一改配置就起不来的情况就只能删容器重新挂了所以容器场景一定要把密码配置固化在启动参数或挂载配置中。6.4 排查技巧学会看Redis日志别瞎猜密码相关故障最快定位方式是看日志。默认Redis日志输出到stdout如果通过systemd运行用journalctl -u redis -f查看如果是容器用docker logs redis-container。出现NOAUTH字样就是认证未通过出现MASTER auth failed就是从库连接主库认证失败出现DENIED Redis is running in protected mode是受保护模式拒绝了远程连接。把这些关键词记下来排查的时候直接按图索骥。我以前总喜欢在客户端反复试命令直到看到日志里明晃晃写着Permission denied我才反应过来是配置问题。经验告诉我出问题先看服务端日志再看客户端日志最后才去猜代码配置。7. 密码管理和安全加固的几条建议设置完密码不等于安全就完事了。Redis的密码只是第一道门后面还有几个细节值得一起做。密码本身要够长够随机不要用123456这种一眼就能猜到的密码。可以用工具生成比如Linux下openssl rand -base64 24生成的字符可能包含/、、这些在URL或配置解析时容易出问题。我更推荐生成32位十六进制字符串用openssl rand -hex 16这样的密码全是字母和数字各客户端配置都友好。密码定期更换也建议纳入运维计划尤其是人员变动频繁的开发环境。换密码时先改服务端再改客户端最后确认客户端生效再观察一段时间不要一股脑全改了才想起来有发现漏改。另外强制建议启用Redis的rename-command来禁用或重命名危险命令比如FLUSHALL、FLUSHDB、KEYS、SHUTDOWN等。配置文件里可以有如下片段rename-command FLUSHALL rename-command FLUSHDB rename-command KEYS some_prefix_keys这样即使密码泄露攻击者也无法直接清空整个Redis。注意重命名KEYS后你的可视化客户端可能也要调整有些客户端会依赖KEYS命令做key扫描重命名后它们会无法工作。所以要根据实际使用场景权衡。另一个容易被忽略的点是不要让Redis监听公网。如果只是内网服务用防火墙把6379端口限制在业务网段内。密码是安全层之一网络隔离是更重要的一层。双重保障才能应对端口扫描、内网渗透等风险。8. 写在最后一次规范配置换来整晚好觉从裸奔到规范配置Redis设置密码这件事操作上不复杂难的是想清楚每个模式的联动关系。单机版改requirepass就够了主从要加masterauth哨兵还要配sentinel auth-pass集群则统一所有节点的密码。每一步都验证一遍不能想当然。我个人在实际操作中的体会是宁可多做几次CONFIG GET确认也别直接拿生产环境赌。尤其改配置之前先用redis-cli -p 6379 INFO REPLICATION记一下当前主从角色避免在从库上改完密码却说“主库为什么连接失败”。如果用了Docker部署尽量把密码写在启动参数或挂载配置文件中这样容器重建后不会丢失配置。最后再分享一个小技巧在配置中心或脚本里管理Redis密码时明文写难免会有泄漏风险有条件的话建议用Vault一类的密钥管理服务配合环境变量注入这样即使日志被打出来也不会直接暴露密码本体。但如果项目比较轻密码靠人工管理那至少保证它的独立性和随机性不要跟数据库、操作系统账号的密码复用同一个。一次规范配置换来的是整晚好觉值得花那十分钟。
返回列表