ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Redis密码配置全攻略:配置文件、Docker容器与命令行实践

Redis密码配置全攻略:配置文件、Docker容器与命令行实践 开头就直接进入主题别绕弯子。Redis设置密码这件事本身不大但你要是没搞明白它的认证机制一旦踩到“改完密码连不上主从了”、“容器环境变量配了没生效”、“redis-cli -a被同事看到”这类坑真的会被折腾得够呛。这篇文章我就把Redis设密码的三种常用场景——配置文件、Docker容器、命令行——完整拆开来讲。每种都会说清楚“为什么这么做”、“操作里有哪些隐藏细节”、“坑在哪里”。适合三类人看刚部署完Redis不知道怎么写密码保护的生产环境维护者、用Docker跑Redis但没有系统化梳理过参数配置的朋友、以及面试前想搞懂requirepass和ACL区别的开发者。1. 先搞清楚Redis的密码认证到底是怎么回事1.1 不设密码的真实风险很多人觉得“Redis嘛我内网用的设什么密码”。我可以负责任地告诉你这个想法相当危险。Redis默认监听在6379端口如果服务器有公网IP或者云安全组规则没收紧任何人都可以扫到你的端口然后直接redis-cli -h 你的IP ping一下如果返回PONG恭喜你你的Redis等于裸奔。更严重的是Redis支持很多危险命令。攻击者不需要密码就能执行FLUSHALL清空你所有数据或者通过CONFIG SET dir、CONFIG SET dbfilename结合SAVE把恶意数据写到服务器上甚至可能配合其他漏洞直接拿系统权限。所以设密码这步不是“可选优化”而是“基础安全配置”。1.2 requirepass与ACL两代认证机制的区别Redis的密码认证经历过两个阶段。Redis 6以前大家用的都是requirepass指令思路特别简单服务器端设置一个全局密码客户端连进来之后必须发送AUTH 密码认证通过才能执行操作。这就好比整栋楼只有一个大门钥匙谁拿着都能进所有房间。Redis 6以后引入了ACLAccess Control List访问控制列表你不再只能设一个全局密码而是可以给不同用户分配不同权限比如某个用户只能读不能写某个用户只能访问指定key还能限制命令类别。“用户密码权限”三个维度解耦比单一requirepass灵活得多生产环境也更推荐。不过这不意味着requirepass就没用了。小项目、内网工具、快速部署场景requirepass依然是最高效的选择。而且ACL的默认用户default user在配置上跟requirepass有对应关系——你设置了requirepass其实就是在给default用户设密码。理解这一点后面看配置文件的逻辑就顺了。2. 配置文件方式最经典也最容易踩坑的场景2.1 找到并修改redis.conf这里先停一下很多人第一步就卡住了。Redis安装方式不同配置文件位置也不一样。源码编译安装配置一般在/usr/local/redis/redis.conf这种路径或者解压目录下。apt/yum安装通常在/etc/redis/redis.conf。Docker挂载方式更灵活你可以把宿主机任意路径的配置文件映射进去。提示不确定配置在哪先执行redis-server --version看版本再执行redis-cli CONFIG GET dir查看工作目录不过更直接的办法是找启动脚本或者systemd服务文件里ExecStart指定的配置路径那里写的一定是实际加载的配置。找到配置文件后搜索requirepass默认情况下这一行是注释掉的。在Redis 6.x版本里你会看到类似这样的内容# requirepass foobared去掉前面的#把foobared改成你自己的强密码比如requirepass YourStrongPassword_2024然后保存退出重启Redis。为什么注释样例叫foobared其实这就是官方文档里的占位符真不是让你用这个当密码。2.2 requirepass与masterauth主从同步场景必须一起设置配置文件方式最容易栽的坑就在这里。如果你只是单机Redisrequirepass就够了。但如果你搭了主从复制主库设置了requirepass从库同步主库数据时就需要一种机制来认证主库。这个机制就是masterauth。从库的配置文件里必须这样设置masterauth YourStrongPassword_2024注意masterauth的值必须跟主库的requirepass一致。我当时第一次搭主从就吃了这个亏主库设了密码从库replicaof也配了结果日志里疯狂刷MASTER - REPLICA sync started失败报错信息是-NOAUTH Authentication required。当时一下就明白了——从库在向主库发起复制请求时它自己也是一个客户端一样要被认证。还有一点不能把主从的认证逻辑跟客户端认证混淆。主库的requirepass是让所有客户端“证明自己是谁”从库的masterauth是“我用什么身份去连接主库”。你可以把主从关系类比成员工刷门禁卡masterauth就是员工自己的卡而requirepass是大楼的门锁。2.3 配置完必须做的事重启与验证修改完配置文件后有两种方式让配置生效一是通过redis-server /path/to/redis.conf带配置路径启动。如果Redis已经在运行你需要先关掉旧进程。我一般习惯用redis-cli shutdown这种方式干净安全不会像直接kill -9那样可能导致数据未落盘。二是不重启在线动态修改这块后面讲命令行方式时详细展开。但在生产环境我非常不建议长期依赖在线改配置而不更新配置文件因为Redis重启后如果加载的还是旧配置文件修改就直接丢失了这种“临时生效”带来的假安全感反而坑人。验证方式也很简单redis-cli ping # 如果返回 (error) NOAUTH Authentication required, 说明密码已生效 redis-cli -a YourStrongPassword_2024 ping # 返回 PONG, 说明认证通过这里有个细节redis-cli -a后面直接跟密码命令行会被shell历史记录保存下来。你敲完这条命令执行history就会发现密码明文躺在里面。安全起见生产环境建议用redis-cli进入交互模式后执行AUTH YourStrongPassword_2024这样不会留在shell历史里。3. Docker容器方式三种姿势与一个经典误区3.1 先搞清楚容器里Redis是怎么加载配置的Docker跑Redis最容易让人困惑的地方是容器里其实也有一份默认配置文件。官方镜像redis的默认工作目录是/data配置文件默认路径是/usr/local/etc/redis/redis.conf。但默认情况下官方镜像启动时如果没指定配置文件Redis是“无配置裸启动”的也就是说所有配置都走默认值。所以容器场景下设置密码本质上有三条路启动时通过命令行参数直接传--requirepass通过环境变量间接传参部分镜像支持挂载宿主机上写好的配置文件并指定加载三种方式各有适用场景下面逐一拆解。3.2 方式一docker run命令行直接传参这是最快最直观的方式docker run -d \ --name redis-test \ -p 6379:6379 \ redis:7.0 \ redis-server --requirepass MyDockerPassword注意redis-server后面跟的参数是给容器内Redis进程的启动参数不是docker run的参数。很多新手会把--requirepass写在docker run的参数位置然后发现完全不生效就是因为传错了地方。这种方式的优点是快速、适合临时测试。缺点也很明显密码直接出现在docker ps或者docker inspect能看到的环境变量/启动命令里如果周围人有服务器权限密码等于泄露了。另外如果你需要配置很多参数命令行会变得又长又乱。3.3 方式二环境变量方式官方Redis镜像本身没有直接提供“REDIS_PASSWORD”这种环境变量来自动设置密码但社区里有些镜像比如bitnami/redis是支持这种方式的。用bitnami镜像时你可以这样docker run -d \ --name redis-test \ -e REDIS_PASSWORDMyBitnamiPassword \ -p 6379:6379 \ bitnami/redis:latest这里必须提醒一句官方镜像不会响应REDIS_PASSWORD这个环境变量。很多人之前被其他软件的习惯带偏了以为设个环境变量就行结果容器起来了密码根本没生效。我在文章里专门提这个是因为这个坑在社区里出现频率太高了。如果你坚持用官方镜像又想集中管理配置最稳妥的办法还是第三种——挂载配置文件。3.4 方式三挂载自定义配置文件这是生产环境最推荐的方式因为配置文件可以纳入版本管理所有参数一目了然。假设你宿主机上有一个/data/redis/redis.conf里面已经写好了requirepass DockerFilePassword appendonly yes启动时挂载进去docker run -d \ --name redis-prod \ -p 6379:6379 \ -v /data/redis/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7.0 \ redis-server /usr/local/etc/redis/redis.conf这里有个很关键的细节-v把宿主机配置文件挂载到容器内路径之后必须在启动命令里显式指定这个配置文件的路径否则Redis还是不会加载它。因为官方镜像默认不会主动去读/usr/local/etc/redis/redis.conf你得告诉它“用这个文件启动”。挂载方式的好处在哪你在宿主机上改配置文件然后重启容器就能生效不用进容器里折腾vi。而且docker inspect里看不到密码明文相对安全。3.5 容器内验证密码是否生效容器启动后验证方式比宿主机上要多一步# 进入容器 docker exec -it redis-prod redis-cli # 在交互模式下直接输入 AUTH DockerFilePassword # 返回 OK或者一条命令验证docker exec -it redis-prod redis-cli -a DockerFilePassword ping # 返回 PONG注意容器内的redis-cli默认连接的是127.0.0.1:6379在容器内验证没问题。但如果你在宿主机上执行redis-cli连接的是宿主机的6379端口前提是你做了-p 6379:6379端口映射否则连不进去。这个区别虽然基础但容易让人误解“密码到底设上去没有”。4. 命令行方式临时修改与持久化的正确姿势4.1 用CONFIG SET在线修改Redis允许在运行状态下通过命令动态修改配置无需重启redis-cli -a 旧密码 CONFIG SET requirepass 新密码如果现在没设密码直接redis-cli CONFIG SET requirepass MyNewPassword这种方式在什么场景下用比如你在排查问题怀疑密码策略导致某客户端频繁重连想临时换个弱密码验证一下或者你只是想在角色切换前快速改密。CONFIG SET是热加载的改了立刻生效所有已连接且未认证的客户端会被要求重新认证。但记住一个核心点CONFIG SET只改内存中的配置不改配置文件。如果Redis重启它还是会加载旧配置密码又变回原样。4.2 CONFIG REWRITE把在线修改持久化有没有办法既在线改又让配置落盘有Redis提供了CONFIG REWRITE命令redis-cli -a 新密码 CONFIG REWRITE这条命令会把当前运行配置重写到配置文件里。它做的事其实是在保留原配置注释结构的基础上把当前生效的参数合并写回文件。如果你之前用CONFIG SET改了一堆参数执行一次CONFIG REWRITE就能全部固化下来。具体使用顺序建议这样# 1. 登录并设置新密码 redis-cli CONFIG SET requirepass MyNewPassword # 2. 用新密码登录并持久化配置 redis-cli -a MyNewPassword CONFIG REWRITE这里有个细节CONFIG REWRITE之后配置文件里会自动出现一行requirepass MyNewPassword而且它比手动编辑配置文件的好处是不容易改坏格式。当然前提是你的Redis进程启动时确实加载了一个可写的配置文件。如果启动时没指定配置文件比如纯默认启动执行CONFIG REWRITE会提示The server is running without a config file这时候它就无能为力了。4.3 redis-cli -a 的泄露风险与替代方案命令行场景还有个绕不开的话题redis-cli -a虽然方便但真的不妥。一方面shell history会记录明文密码。尤其在生产环境别人通过history或者~/.bash_history文件就能看到。另一方面如果你在写脚本时用-a传密码脚本文件本身的权限控制不好也会泄露。替代方案有两个一是用REDISCLI_AUTH环境变量替代-a参数。这是redis-cli内置支持的环境变量设置后会自动作为默认认证密码传给每次连接export REDISCLI_AUTHMyNewPassword redis-cli ping # 返回 PONG好处是连接命令简洁而且ps进程列表里不会出现明文密码因为密码是运行时从环境变量里读取的不过环境变量本身也有泄露风险使用时注意控制shell会话权限。二是用交互模式手动AUTHredis-cli 127.0.0.1:6379 AUTH MyNewPassword OK 127.0.0.1:6379 PING PONG这种方式适合临时操作不会在shellhistory里留下密码痕迹。我个人在排查生产问题时只要不是脚本化操作基本都用交互模式。5. 常见问题与排查技巧实录5.1 设置密码后提示NOAUTH Authentication required这个报错其实是个好消息说明密码验证已经开始工作了。它出现在两种情况一种是你没带密码就执行命令。比如redis-cli ping (error) NOAUTH Authentication required.解决方案就是先AUTH再操作。另一种情况比较隐蔽主从复制里从库连接主库时由于masterauth没配或配错也会报这个错。排查时先看从库日志关键字是MASTER - REPLICA sync started后面跟着认证失败信息。我一般用三步排查这个问题确认主库CONFIG GET requirepass能看到密码。确认从库CONFIG GET masterauth配置了同样的密码。如果两边都正确检查从库执行CONFIG GET masterauth和CONFIG GET requirepass是否被重启后重置了比如从库依赖的命令行启动参数覆盖了配置文件的masterauth。5.2 Redis Desktop Manager连接不上经常有朋友说“Redis Desktop Manager连不上用命令行能连”。多数情况不是密码问题而是RDM默认用TCP连接到目标IP的6379端口如果Redis只绑定了127.0.0.1外部客户端自然连不上。检查以下几项Redis进程里CONFIG GET bind返回的IP是什么如果是127.0.0.1改用0.0.0.0或具体内网IP。云服务器安全组是否放行6379端口。Redis的protected-mode是否开启。默认情况下protected-mode是yes它要求只能来自回环地址的连接才能无密码访问外部IP必须密码认证。在RDM里填密码的位置对应的是requirepass也就是默认用户的密码。如果版本较新还支持配置ACL用户那要单独指定用户名。5.3 修改密码后主从同步失败这种情况多半是只改了主库的requirepass忘了同步改从库的masterauth。Redis主从复制从库要模拟一个客户端连主库它的身份验证靠的就是masterauth。主库密码换新从库还拿旧密码认证自然被拒绝。解决方式# 在主库上改密码 redis-cli -a 旧密码 CONFIG SET requirepass 新密码 # 在从库上同步修改masterauth redis-cli -a 旧密码 CONFIG SET masterauth 新密码 # 两边都执行CONFIG REWRITE确保重启后不丢失另外Redis 7.x版本里还可以用CONFIG SET replicaof重新指定主节点但核心还是认证信息要对得上。5.4 日志中的WARNING提示“Current password is empty”Redis在开启某些安全相关特性时会输出警告比如当protected-mode设为yes时如果没设密码日志会提示Warning: no config file specified, using the default config.等相关信息。这类警告本身不致命但它提醒你当前Redis处在“仅内网访问、无密码”的状态如果网络隔离做得不够好还是趁早加上密码。5.5 忘记Redis密码怎么办忘记密码是每个运维都可能遇到的事。这时候不用慌有两个方案一是如果Redis启动时没有加载配置文件你可以直接停掉Redis然后临时用--requirepass 起一个空密码实例把数据导出来再用正常配置启动。但这个方法在容器里比较麻烦不建议在生产环境乱搞。二是从配置文件里找回因为CONFIG REWRITE之后密码会明文写入配置文件。但如果配置文件是只读权限你可能需要root权限才能读。最惨的情况是启动时没有配置文件也没做过CONFIG REWRITE那内存里的密码理论上无法直接读取。这时候只能重启Redis并设置新密码。由于Redis在关闭时若开启了appendonly数据会以AOF形式保存在磁盘上即使重启换密码数据也不会丢。不过重启前最好先确认这个节点是否为主节点如果为主节点涉及主从切换或客户端重连尽量选业务低峰期操作。5.6 生产环境加密码的几个实操建议最后补充几个我踩过坑后总结出来的经验第一密码不要写在命令行里不要写在docker run的启动命令里除非是临时测试。时间久了你会发现最简单安全的办法还是配置文件统一管理。第二密码强度要有底线但别复杂到自己都记不住。很多团队选择用固定格式比如“项目代号年份随机字符”既方便记忆又不容易被猜到。网上大量扫描器还停留在跑默认密码foobared和简单字典阶段用个中等强度的随机密码就足够挡掉大部分扫描。第三改了密码之后第一时间检查所有调用了Redis的服务。比如Java Spring Boot项目里的redis.password配置、Python的redis.Redis(password...)、Node.js的ioredis初始化参数等。经常有人密码在主库改好了业务侧没同步服务连不上才开始排查白白浪费半天时间。第四如果是Redis 6以上版本且是多团队共享实例认真考虑用ACL按团队分用户。你可以给A团队一个只读只读自己key前缀的用户给B团队一个能执行特定命令集但不能FLUSHALL的用户比一个全局requirepass给所有人要好管控得多。当然这属于密码之上更细粒度的权限设计等你有需求再来折腾不迟。Redis设置密码这个动作看起来就是一行配置的事但真正落到不同部署环境、不同拓扑结构里细节还挺多。我自己在实际操作中的体会是不管用哪种方式先在测试环境完整跑一遍“修改密码、验证登录、检查主从、确认业务侧恢复”的闭环再上生产能帮你避开大部分“改完密码服务全挂”的尴尬局面。
返回列表