老规矩,先摆一个真实场景:你刚装好Redis,本机一切正常,缓存读写得飞起。然后你把它部署到一台有公网IP的服务器上,开了默认端口6379,第二天一看日志,有人不仅在连你的Redis,还往里面写了一堆定时任务、挖矿脚本,甚至直接把你数据库里的键值清空了。这种事不算罕见,十次有八次是因为Redis装好之后压根没设密码。
Redis默认配置里是不需要认证的,服务启动后任何人只要知道IP和端口,就可以直接连上去操作所有数据。这跟把家门钥匙挂在门口差不多。所以“Redis如何设置密码”这件事,不是锦上添花,是上线前的必做动作。这篇文章从最基础的配置文件改密码开始,把命令行临时设置、Docker容器、主从复制、可视化客户端连接这些场景全部过一遍,顺便把我自己踩过的坑和排查方法一并分享出来。
1. 为什么Redis一定要设置密码:从一次“裸奔”说起
1.1 不设置密码会怎样
Redis默认监听0.0.0.0,也就是说只要服务器有公网IP,6379端口暴露出去,任何人在任何地方都能用redis-cli连上来。攻击者不需要爆破密码,因为压根没有密码。常见的利用方式包括:
- 用
FLUSHALL清空你的所有数据,再写入勒索信息。 - 写入crontab计划任务,反向连接下载挖矿程序。
- 如果Redis以root权限运行,配合写文件功能,甚至可能把SSH公钥写进服务器,拿到系统权限。
这不是危言耸听,网上大量Redis未授权访问的漏洞通报都是真实案例。很多人觉得“我就内网用一下”“开发环境无所谓”,可内网一旦被横向打穿,开发环境同样会成为跳板。
1.2 Redis密码机制的底层逻辑
Redis的密码认证靠两个东西:requirepass配置项和AUTH命令。简单理解:
- 你在
redis.conf里设置requirepass yourpassword,服务启动后,Redis进入“需要认证”状态。 - 客户端连接后,如果没发
AUTH yourpassword,执行任何命令都会返回NOAUTH Authentication required。 - 认证通过后,在当前连接会话内就可以正常读写。
从Redis 6.0开始,官方还引入了ACL(Access Control List),可以给不同用户设置不同权限和不同密码。requirepass本质上是在给默认用户(default)设置密码,属于ACL体系里最基础的一种用法。对于绝大多数场景,设置requirepass已经能满足安全需求;如果要更细粒度地控制某些命令只允许特定应用使用,再去研究ACL也不迟。
注意:
requirepass设置的是明当前实例的认证密码,是全局的,所有客户端连进来都用同一个密码。
2. 最常用做法:修改redis.conf并重启服务
2.1 先找到正确的配置文件
不同安装方式,redis.conf位置完全不同,这一步错了后面全都白搭。
- 源码编译安装:通常在
/usr/local/redis/redis.conf,或者你编译时用--prefix指定的目录下。 - apt/yum 安装:通常在
/etc/redis/redis.conf。 - Windows解压版:一般在解压目录下,常见名字是
redis.windows.conf或者redis.conf。 - Docker容器:镜像默认没有持久化配置文件,稍后单独讲。
如果你不确定Redis到底读的哪个配置文件,有两种办法确认:
- 用
redis-cli info server查看config_file字段。 - 看启动命令:
ps -ef | grep redis,启动参数里如果有/path/to/redis.conf,那个就是实际生效的配置文件。
这步很关键,我见过有人改了半天/etc/redis/redis.conf,结果Redis是用源码编译安装的,实际读的是/usr/local/redis/redis.conf,改完重启,密码自然没生效。
2.2 四步完成配置修改与重启
假设你确认了配置文件路径,操作步骤如下:
第一步,备份原配置,以防手滑:
cp /etc/redis/redis.conf /etc/redis/redis.conf.bak第二步,编辑配置文件,找到# requirepass foobared这一行,删掉注释并改成你的密码:
vim /etc/redis/redis.confrequirepass 你的强密码建议密码不少于16位,包含大小写字母、数字和特殊字符。但要注意,如果你的配置文件中密码里有#号,这个符号在某些命令行工具或脚本里会被当作注释开头,引发各种诡异问题。所以我个人建议:密码不一定要最复杂,但尽量不要包含#、空格、单引号、双引号这类容易在配置解析和脚本传参时出问题的字符。比如Redis@2024#Prod这种就比Redis@2024-Prod更容易踩坑。
第三步,重启Redis服务。
如果是systemd管理:
sudo systemctl restart redis如果是手动启动的:
# 先杀掉旧进程 redis-cli shutdown # 再重新启动 redis-server /etc/redis/redis.conf第四步,验证密码生效。
redis-cli 127.0.0.1:6379> keys * (error) NOAUTH Authentication required.看到这个提示,说明密码已经生效。
2.3 如何验证密码已经生效
认证通过后再执行命令:
127.0.0.1:6379> AUTH 你的密码 OK 127.0.0.1:6379> keys * (empty array)也可以用一条命令带密码直接登录并执行:
redis-cli -a '你的密码' ping这时会返回PONG。注意,-a参数在命令行里会明文展示密码,如果服务器上还有其他人在看进程列表,密码会暴露在ps输出里。更好的做法是设置环境变量REDISCLI_AUTH:
export REDISCLI_AUTH='你的密码' redis-cli ping这样进程列表里就不会出现密码了。
2.4 常见细节与避坑:权限、多个配置文件混淆
几个我实际踩过的坑,列给你:
- 改的是
redis.windows.conf,但Windows服务启动时读的是redis.conf或注册表里的启动参数,导致密码不生效。 - 用apt装的Redis,systemd服务脚本里指定了
--supervised systemd,实际上还是读/etc/redis/redis.conf,没问题;但如果你改的是当前目录下自以为的配置文件,那就是白改。 - 配置文件末尾如果有多行
requirepass,Redis优先使用最后一个。所以别在文件后面追加新配置,应该修改原行。 - 修改配置后必须重启服务。有些参数支持
CONFIG SET热加载,但save、appendonly这类涉及磁盘和进程的参数建议重启确保完全生效。requirepass其实可以热加载,但为了方便统一,我建议使用CONFIG SET,见下一节。
3. 临时改密码与常用命令行操作
3.1 用CONFIG SET临时设置密码
有些场景不想重启Redis,比如线上实例,重启意味着短暂不可用。这时可以用CONFIG SET动态设置:
redis-cli 127.0.0.1:6379> CONFIG SET requirepass '新密码' OK执行完这条命令后,当前连接不受影响,但其他已有连接会被立即要求重新认证(准确说,已认证的连接仍然能继续操作,但新连接必须认证)。这里的坑在于:CONFIG SET只改内存配置,不改磁盘上的配置文件。如果此时Redis重启,密码又回到原来的状态。
所以正确的组合拳是:
redis-cli -a '旧密码' 127.0.0.1:6379> CONFIG SET requirepass '新密码' OK 127.0.0.1:6379> CONFIG REWRITE OKCONFIG REWRITE会把当前内存中的配置重写回redis.conf文件。注意,执行CONFIG REWRITE时,如果配置文件中原本就有requirepass行,会被更新为新值;如果原本没有,会在文件末尾追加。
这里有一个很隐蔽的问题:如果Redis启动时是通过--requirepass参数指定密码,而不是通过配置文件,CONFIG REWRITE之后,密码虽然写进了配置文件,但下次服务重启时如果启动脚本里又带着--requirepass,这个参数会覆盖配置文件里的设置。所以排查密码不生效时,一定要看启动命令里的参数。
3.2 用CONFIG REWRITE固化配置
CONFIG REWRITE这条命令在修改Redis配置时非常实用,不只是密码,其他动态参数也可以这样固化。但要记住几个前置条件:
- Redis进程对
redis.conf文件必须有写权限。如果Redis是由root启动的,配置文件是root属主,那没问题;如果Redis由redis用户启动,配置文件却是root属主,CONFIG REWRITE会报错ERR Rewriting config file: Permission denied。 - 配置文件路径必须是通过正常方式启动时加载的。如果你是用
redis-server不带配置参数启动的,CONFIG REWRITE会尝试写到编译时默认路径,通常也有权限问题。
提示:改完密码后,建议立刻执行
CONFIG REWRITE,并确认输出OK。这样至少保证配置落盘,不会因为重启把密码改没了。
3.3 通过启动参数传密码(systemd / 手动启动场景)
有些情况下你不想改配置文件,或者临时想给某个实例单独指定密码,可以直接在启动命令里加参数:
redis-server --port 6380 --requirepass '实例密码'systemd管理的Redis服务,如果有特殊需求,可以通过编辑unit文件实现:
sudo systemctl edit redis这会创建一个override.conf,加入:
[Service] ExecStart= ExecStart=/usr/bin/redis-server /etc/redis/redis.conf --requirepass '你的密码'注意第一行ExecStart=是必须的,因为systemd里后面出现的ExecStart会覆盖前面的,必须先清空再重新赋值,否则参数堆叠反而出问题。
用这种方式设置密码,优先级高于配置文件,适合“只在某个实例上用密码,不影响其他实例”的场景。缺点是不够直观,查看配置时容易漏掉,建议在配置文件头部写好注释。
4. 进阶:容器化环境下的密码设置(Docker与K8s)
4.1 Docker容器中的Redis密码设置方式
现在很多项目直接用Docker跑Redis,不涉及传统的配置文件修改。此时设置密码有两种思路。
第一种,启动时直接传参:
docker run -d --name redis \ -p 6379:6379 \ redis:7.0 \ redis-server --requirepass '你的密码' --appendonly yes注意镜像后面那一串redis-server --requirepass是覆盖镜像默认命令的写法。因为官方镜像的默认入口就是redis-server,后面跟参数可以透传进去。这种方式适合快速起一个临时实例,但密码写在命令行里,其他人通过docker inspect能看到。
第二种,挂载自定义配置文件:
docker run -d --name redis \ -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在宿主机上先准备好/data/redis/redis.conf,里面写入requirepass等配置,挂载进容器。这种方式更可控,也方便持久化其他调优参数。
4.2 docker-compose配置实例
实际项目里用docker-compose更常见,我贴一个完整的例子:
version: '3.8' services: redis: image: redis:7.0 container_name: redis restart: always ports: - "6379:6379" command: ["redis-server", "--requirepass", "Compose-Pass-2024", "--appendonly", "yes"] volumes: - redis-data:/data volumes: redis-data:这里通过command列表形式传参,比字符串形式更安全,避免引号嵌套导致解析错误。里面的Compose-Pass-2024替换成你自己的密码。
启动:
docker-compose up -d测试:
docker exec -it redis redis-cli -a 'Compose-Pass-2024' ping4.3 使用Kubesphere/云原生环境部署时的密码透传
如果是在Kubernetes或Kubesphere这类云原生平台部署Redis,不太建议把密码硬编码在镜像或配置文件里。常见做法:
- 用Secret保存密码,部署时挂载为环境变量。
- Redis的启动命令从环境变量读取密码。
举个例子,在Kubesphere创建Redis部署时,可以在StatefulSet的容器启动命令中引用环境变量:
containers: - name: redis image: redis:7.0 command: - sh - -c - | redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-secret key: password原理不复杂:容器启动时,先用shell把环境变量展开,再传给redis-server。好处是密码不会直接出现在镜像、Pod定义或日志里,即使别人看到了Pod YAML,也只能看到引用名而看不到明文。
注意:如果你在Kubesphere的“应用模板”或“服务组件”里只填了一个password字段,实际传递给Redis的环境变量名未必是
REDIS_PASSWORD,要看模板实现。很多模板会自己处理密码注入,也有模板直接把密码放到了配置文件里,注意区分。
5. 主从复制、客户端连接和常见问题排查
5.1 主从架构的密码设置:masterauth参数
到了主从复制环境,只设置主库密码是不够的。从库同步数据时,它也是作为一个“客户端”去连接主库的,所以在从库上必须单独配置masterauth,告诉从库用哪个密码连接主库。
假设你的主库设置了requirepass MasterPass@2024,从库配置文件需要加入:
masterauth MasterPass@2024如果不写,从库日志会一直出现MASTER <-> REPLICA sync started后紧跟MASTER aborted replication with an error: NOAUTH Authentication required,同步始终建立不起来。
主库、从库、哨兵三者的密码关系可以这样理解:
- 对普通客户端来说,连主库或从库都要提供该实例自己的
requirepass密码。 - 对从库来说,它连主库时要提供主库的密码,即
masterauth。 - 对哨兵来说,它连接主库、从库、其他哨兵时,需要配置
sentinel auth-pass <master-group-name> <password>。
注意,如果从库本身也开启了requirepass,那么客户端连从库也需要认证,这跟同步主库的密码是两回事,别混在一起。
5.2 修改密码后,客户端连接失败怎么办
改完密码,最常见的故障就是应用程序突然报错,常见的错误信息是:
NOAUTH Authentication required或:
WRONGPASS invalid username-password pair or user is disabled排查思路按顺序来:
- 确认Redis实例当前的
requirepass值:redis-cli CONFIG GET requirepass。这个命令不带密码也能执行,但返回结果如果没认证,会显示空值。带密码认证后执行,就能看到实际配置的值。 - 确认应用的配置是否更新。很多人改了Redis密码,但项目里的配置文件、环境变量还是旧密码,比如Spring Boot的
spring.redis.password没改,或者Python的redis.Redis(password=...)没改。 - 区分环境,生产、测试、Redis管理工具、命令行连的可能是不同实例。尤其本地有Redis、服务器也有Redis时,
redis-cli -h 127.0.0.1和redis-cli -h 服务器IP完全两回事。
以Python为例,连接时带上密码:
import redis r = redis.Redis( host='127.0.0.1', port=6379, password='你的密码', decode_responses=True ) r.set('foo', 'bar') print(r.get('foo'))以Java Spring Boot为例,修改application.yml:
spring: redis: host: 127.0.0.1 port: 6379 password: 你的密码 timeout: 3000ms改完配置记得重启应用,因为很多框架的连接池在启动时就建立了连接,不会动态切换密码。
5.3 Redis Desktop Manager可视化客户端连接步骤
推荐直接用开源免费的Another Redis Desktop Manager(通常简称ARDM),比老牌的Redis Desktop Manager更轻量,跨平台支持也好。连接时在“New Connection”对话框里,填好Host、Port,再在Auth一栏填密码。注意如果Redis端口不是默认6379,要写对。
连接成功后,在左侧列表能看到键的树形结构,能执行常用命令、查看TTL、修改值类型。需要注意的一点:有些版本的客户端工具要求填写用户名,默认用户就叫default,密码填requirepass设置的密码即可。如果你用了ACL创建了其他用户,那用户名就填对应的用户名。
如果连接时提示AUTH <password>: WRONGPASS invalid username-password pair,先确认密码复制时有没有多空格、少字符,再确认Redis是6.0以上的ACL模式,也许你真正该填的是default这个用户名加对应密码,而不是空的用户名。
5.4 高频报错与排查速查表
汇总一下我常遇到的问题,方便对照:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 本地连接提示NOAUTH | 密码已生效,客户端还没认证 | 执行AUTH 密码或配置客户端密码 |
| 应用报NOAUTH | 应用配置没更新 | 检查项目配置文件、启动参数、环境变量 |
| 重启后密码失效 | 用的是CONFIG SET但没执行CONFIG REWRITE | 登录后执行CONFIG REWRITE并检查配置落盘 |
| 改配置文件不生效 | 改错了实际加载的配置 | 用CONFIG GET dir配合ps确认读写文件路径 |
| Windows下密码没生效 | Windows服务启动参数覆盖了配置文件 | 检查服务属性里的“启动参数”,去掉多余--requirepass |
| 从库同步报NOAUTH | 从库没有配置masterauth | 在从库配置中加入主库密码并重启 |
| 哨兵连不上主库 | 哨兵没配置sentinel auth-pass | 在哨兵配置中加入主从密码 |
含#密码出现诡异报错 | #被当成注释或shell转义 | 更换为字母数字加常规符号的密码 |
| 容器里日志一堆NOAUTH | 容器启动命令与外部配置冲突 | 确认容器command是否覆盖了配置文件里的requirepass |
| CONFIG REWRITE报权限拒绝 | 文件属主与Redis进程用户不一致 | chown或对redis用户赋写权限 |
5.5 Windows下Redis设置密码的独特坑
Windows下Redis的玩法和Linux不一样。最常见的是解压版,里面有两个配置文件:redis.windows.conf和redis.windows-service.conf。如果你是用命令行启动的:
redis-server redis.windows.conf那改redis.windows.conf即可。如果你把它注册成Windows服务:
redis-server --service-install redis.windows-service.conf那服务启动时读的是redis.windows-service.conf,改另一个文件就不生效。这一点特别容易搞混,我的建议是:干脆把两个配置文件里的requirepass都改掉,避免后续手忙脚乱。
另外,Windows服务方式启动的Redis,如果服务已经在运行,改完配置需要重启服务:
net stop redis net start redis或者直接用服务管理器重启。改完后再用redis-cli验证一下,确保没有缓存旧密码。
结尾:说点个人体会
在给很多项目做Redis加固的过程中,我最大的感受是:绝大多数Redis安全事件,都不是因为配置复杂,而是因为“默认没密码”这件事被忽略了。很多人装完Redis就忙着写业务代码,等到日志里出现陌生IP才反应过来。设置密码本身不难,难的是把密码管起来:密码放在哪、怎么轮换、主从怎么同步、容器怎么透传、应用怎么感知,这些都要提前想清楚。
如果让我给一个最佳实践的清单,我的建议是:生产环境至少16位随机密码,放密钥管理或环境变量里,不要硬编码进代码;Linux服务器上用systemd管理Redis时,优先改配置文件而不是启动参数;Docker环境里用compose管理并在command里传参;主从环境把masterauth写进从库配置;每次改完密码,花30秒用redis-cli验证一下,再检查应用日志,别让运维群里突然冒出告警。
Redis是一个效率极高的工具,正因如此,它的安全底线更应该自己守住。这篇内容基本把我遇到的相关问题都过了一遍,希望给卡在密码设置上的朋友省点时间。