☰
Redis密码认证全攻略:从requirepass到主从复制安全配置
2026/9/30 3:17:20 网站建设 项目流程

刚把一个新环境的Redis部署好,用redis-cli敲了个ping,看着终端回了个PONG,心里还挺舒坦。结果没几天,安全扫描报告直接标红:6379端口对外开放,无认证,存在未授权访问风险。这类事儿在开发环境里太常见了——Redis默认配置只允许本机访问,但如果你的机器绑定了公网IP、或者用了云数据库的内网映射、又或者容器启动参数写得宽松,端口一旦暴露,Redis就会变成攻击者眼里的“免费资源池”。轻则CPU被打满跑挖矿脚本,重则数据被删勒索。给Redis设置密码,就是解决这个问题的第一道闸门。

这篇文章我打算把Redis密码认证这块从头到尾捋一遍:为什么Redis默认不设密码、密码机制是怎么工作的、Linux、Windows、Docker、主从复制、可视化客户端不同场景下怎么配、以及那些经常踩的坑怎么排。不管你是刚接触Redis的新手,还是已经用了很久但从来没关注过认证这块的老手,这篇都能给你一点参考。

1. 为什么Redis一装好就应该先设密码

1.1 Redis默认配置的安全弱点

Redis的出厂配置走的是“高性能、低约束”路线。默认情况下,redis.conf里的bind 127.0.0.1只允许本机回环地址访问,protected-mode yes会在没有密码且没有自定义bind的情况下自动拒绝远程连接。看起来还算安全,但这里有两个隐患。

第一个隐患是,很多人在“快速上手”教程的引导下,会把bind注释掉,或者改成0.0.0.0,让Redis能被外部访问,方便调试。这时候如果protected-mode还是yes,Redis确实会拒绝非本机连接,可一旦你为了省事把protected-mode no也写上了——那一台裸奔的Redis就彻底暴露了。

第二个隐患藏在云环境和容器环境里。云厂商的默认安全组规则、Docker的-p 6379:6379端口映射、Kubernetes的NodePort暴露,都可能绕过bind 127.0.0.1的限制。而protected-mode只在“没有配置密码”和“没有显式bind”同时成立时才生效,你只要改了bind,保护模式基本就失效了。所以本质问题是:默认配置本身就不是为“暴露在外网”设计的,一旦网络环境变了,Redis不会自动帮你加一道防线。

1.2 不设密码可能遇到的真实风险

我在实际工作里见过不止一次Redis未授权访问事故,类型无外乎以下几种。

最常见的是入侵者用redis-cli连上之后执行CONFIG SET dir /var/spool/cron/、CONFIG SET dbfilename root、SAVE这类组合命令,把恶意计划任务落到服务器上,实现反弹shell或持久化控制。这个攻击路径早期在CentOS上很成熟,虽然现在系统防护意识普遍提高,但低版本系统上依然有效。

第二种是挖矿脚本。攻击者扫描全网开放6379的端口,连上后执行SLAVEOF或者直接写入恶意配置,把CPU资源劫持去挖门罗币。这类攻击有个典型特征:redis-cli连上去之后,发现配置文件里多了诡异的dir和dbfilename设置,进程CPU占用率飙到100%,白名单外的陌生进程在跑。

第三种最无解——数据被删。攻击者不需要任何利用技巧,直接执行FLUSHALL然后设置一个SET,留下联系方式勒索赎金。对于只把Redis当缓存用的团队,数据丢了可以从数据库恢复;但如果里面存了Session会话、未入库的业务状态,恢复起来非常痛苦。

所以,设置密码这件事不是“安全团队要求”的条条框框,而是Redis暴露边界扩大之后不得不做的基本操作。尤其在生产环境,密码认证、bind限制、rename高危命令是三层必须同时上的保险。

1.3 设了密码能解决什么,不能解决什么

给Redis设置requirepass之后,客户端连接时必须先执行AUTH <password>,否则Redis会返回NOAUTH Authentication required错误,所有读写命令都无法执行。这对上面提到的三种攻击方式——未授权写入、配置篡改、数据清空——能起到直接拦截作用,因为攻击者不知道密码,连大门都进不去。

但必须说清楚,密码不是万能钥匙。如果你的Redis暴露在公网且密码很弱,比如123456、redis123,暴力破解只是时间问题。另外,Redis的认证过程本身是明文传输的密码,如果不启用TLS(Redis 6.0及以上支持TLS),在内网抓包的环境下密码会被直接看到。密码能防“路人攻击”,防不了“有备而来的内鬼或者能抓包的入侵者”。所以在架构层面,Redis服务尽量别暴露公网,内部网络也要做隔离,密码只是安全体系中的一环。

2. Redis密码认证的工作机制

2.1 requirepass、AUTH命令和默认用户的关系

Redis的密码认证核心就是一个配置项:requirepass。但这个配置项在Redis 6.0之后有了更精确的定位——它本质上是在给Redis ACL体系中的“默认用户”(default user)设置密码。Redis 6.0引入了完整的ACL(Access Control List)机制,支持创建多个用户、给每个用户分配不同的命令权限和键空间权限,而requirepass就是老版本流传下来的“快捷方式”,作用等价于ACL SETUSER default >密码。

理解这一点对排查问题很有帮助。比如你在Redis 6+上配置了requirepass,但又额外用ACL创建了新用户,这两个体系是并存的:AUTH <密码>走的是default用户认证,新用户得用AUTH <用户名> <密码>的方式认证。如果只设置了requirepass,新用户没有配置密码,那新用户依然无法登录,因为ACL默认新用户是off状态。

2.2 客户端连接时的认证流程

当一个Redis客户端发起TCP连接后,Redis服务器不会立即拒绝它,但任何命令执行前都会检查该连接是否已通过认证。流程大体如下:

  1. 客户端建立TCP连接。
  2. 客户端发送第一条命令,比如GET foo,服务器返回-NOAUTH Authentication required。
  3. 客户端发送AUTH <password>,服务器校验通过后返回+OK。
  4. 之后的命令正常执行,当前连接保持认证状态,无需重复认证。

如果用redis-cli连接,最直接的方式是redis-cli -a yourpassword,这样客户端会在握手阶段自动发送AUTH命令。也可以先连接再手动执行AUTH yourpassword。需要注意,redis-cli -a方式启动时会打印警告:Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe,因为密码会出现在shell历史记录和进程列表里。建议用环境变量REDISCLI_AUTH来传密码,避免命令行明文泄露。

2.3 密码在网络中是怎么传输的

这一点要特别提醒:Redis的AUTH认证在非TLS连接下是明文传输的,也就是说,如果有人在你和应用服务器之间做了网络抓包,密码直接就能看到。Redis从6.0版本开始支持TLS加密,配置tls-port和证书之后,才能做到密码密文传输。所以生产环境对安全要求较高的话,要么控制网络访问范围,要么上TLS,二选一的胆子都不能有——光靠密码扛不住抓包。

还有一个容易被忽略的细节:CONFIG GET requirepass返回的也是明文密码,只要你能连上Redis并拥有CONFIG权限,就能看到密码。因此在高安全场景下,还需要用rename-command CONFIG把CONFIG命令改成一个只有内部知道的名称,防止普通开发者甚至攻击者通过CONFIG命令获取关键配置。

2.4 设置密码之后对性能影响大可放心

很多人担心加了密码认证会对Redis的QPS产生影响。实际测试下来,影响微乎其微。Redis的AUTH验证是一次性操作,在连接建立时完成,只要连接不重建就不需要反复认证。Redis自己的benchmark工具redis-benchmark在带密码场景下测试,性能差异通常在1%以内,可以忽略不计。唯一需要注意的是,如果业务代码在每次操作前都重新创建连接,高频建连场景下认证开销会放大,但这属于连接池使用问题,不是密码本身的问题。

3. 不同环境给Redis设置密码的实操方法

3.1 Linux环境标准配置流程

Linux上通过源码或包管理器安装Redis后,配置文件默认在/etc/redis/redis.conf或安装目录下的redis.conf。我用的是官方源码编译的方式,配置文件就在/usr/local/redis/redis.conf,下面按步骤来。

第一步,修改配置。用vim打开redis.conf,找到# requirepass foobared这一行,把注释去掉,改成自己的密码。密码建议用强密码,至少16位,包含大小写字母、数字和特殊符号。比如:

vim /usr/local/redis/redis.conf

把:

# requirepass foobared

改成:

requirepass YourStrongPassword2024!

第二步,重启Redis。如果Redis是以systemd服务方式管理的,执行:

systemctl restart redis

如果是手动启动的,先找到Redis进程,kill掉再重新用配置启动:

pkill redis-server /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf

第三步,验证效果。先用无密码方式尝试连接,看是否被拒绝:

redis-cli ping # 输出: (error) NOAUTH Authentication required.

然后带密码连接:

redis-cli -a YourStrongPassword2024! # 输出: Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.

接下来执行ping,正常返回PONG。再用CONFIG GET requirepass确认密码已经生效:

127.0.0.1:6379> CONFIG GET requirepass 1) "requirepass" 2) "YourStrongPassword2024!"

3.2 Windows环境配置方法

Windows上使用Redis基本都是用tporadowski或类似社区维护的Windows移植版。Windows版本的Redis配置文件不叫redis.conf,而是叫redis.windows.conf。如果你下载的是解压版,操作步骤如下。

打开命令行,进入Redis目录,先用配置启动一次,让配置生效:

cd C:\redis redis-server.exe redis.windows.conf

注意,如果直接双击redis-server.exe启动,它用的是内置默认配置,不会加载redis.windows.conf里的requirepass。很多人踩的坑就在这里——明明配置文件改了密码,双击启动后却不需要密码,就是因为没指定配置文件。

如果想把Redis注册成Windows服务,用以下命令:

redis-server.exe --service-install redis.windows.conf --service-name Redis

服务名可以自定义。注册成功后通过redis-cli.exe -a YourStrongPassword2024! ping验证一下。如果启动服务时报错,检查配置文件中logfile路径是否存在,Windows移植版对路径格式要求比较严格,经常因为日志目录不存在导致服务起不来。

Windows版Redis还有一个常见麻烦:配置文件里如果用了dir ./,而服务的工作目录不是Redis目录,RDB或AOF文件的路径就会落在莫名其妙的位置,甚至导致服务启动失败。建议把dir改成绝对路径,比如dir C:\redis\data,并且提前建好目录。

3.3 Docker容器里的密码配置

Docker运行Redis时,有三种方式设置密码,按推荐程度排序。

方式一,通过启动命令直接传参,不修改任何文件,适合快速验证:

docker run -d --name redis \ -p 6379:6379 \ redis:7.2 redis-server --requirepass YourStrongPassword2024!

这里redis-server --requirepass YourStrongPassword2024!是覆盖容器默认启动命令并追加参数,效果等同于在配置里设置requirepass。

方式二,挂载自定义配置,适合需要大量自定义参数的场景:

docker run -d --name redis \ -p 6379:6379 \ -v /docker/redis/redis.conf:/etc/redis/redis.conf \ redis:7.2 redis-server /etc/redis/redis.conf

宿主机的/docker/redis/redis.conf里预先写好requirepass项。

方式三,用docker-compose管理,生产环境最常用:

services: redis: image: redis:7.2 container_name: redis ports: - "6379:6379" command: redis-server --requirepass YourStrongPassword2024! volumes: - redis-data:/data volumes: redis-data:

配置好后:

docker-compose up -d

进入容器验证:

docker exec -it redis redis-cli -a YourStrongPassword2024!

这里有个实际经验要分享:Docker容器里如果只是测试,直接用--requirepass最简单;但一旦用了--requirepass,容器内的redis.conf并不会被修改,重启容器后密码由启动命令重新注入,只要命令不变密码就不会丢。这种方式的问题在于密码会出现在docker inspect输出里,对保密要求高的环境还是用配置挂载更干净。

3.4 主从复制场景下masterauth的配置

主从复制是Redis高可用架构的地基,设置密码后主从之间也必须同步认证配置。假设主节点启用了requirepass,从节点要通过认证才能拉取主节点的数据流,需要配置masterauth。

主节点redis.conf中设置:

requirepass YourMasterPassword

从节点redis.conf中设置:

replicaof master-ip 6379 masterauth YourMasterPassword

如果不配masterauth,从节点日志会反复报错:MASTER <IP>:<PORT> -> REPLICAOF: Master replied to PING, replication can be continued...,或者干脆停留在SYNC with master in progress状态,全量同步永远完不成。

如果是Docker部署的主从,主从节点的启动命令可以这样写:

主节点:

docker run -d --name redis-master \ redis:7.2 redis-server --requirepass MasterPass --appendonly yes

从节点:

docker run -d --name redis-slave \ --link redis-master:master \ redis:7.2 redis-server --replicaof master 6379 --masterauth MasterPass --requirepass SlavePass

从节点自己也可以设置requirepass,用于保护对外提供读服务的连接。另外,哨兵集群也一样,每个哨兵节点需要配置sentinel auth-pass <master-name> <password>,否则哨兵无法检测主节点的真实状态,也不能自动故障转移。

3.5 动态设置密码与配置持久化

有时候生产环境正在跑着的Redis不方便重启,可以用运行时命令动态改密码:

127.0.0.1:6379> AUTH OldPassword OK 127.0.0.1:6379> CONFIG SET requirepass NewPassword OK

执行之后,新连接必须用新密码认证,已经认证过的旧连接不受影响,仍是已认证状态。这一点很容易踩坑——如果你动态改了密码,已经连接的老客户端还能继续跑,直到连接断开重连才会发现密码变了。

但CONFIG SET只是改内存中的配置,不会自动写入磁盘文件。Redis 5.0及以上版本支持CONFIG REWRITE,把当前生效的配置覆盖写回配置文件:

127.0.0.1:6379> CONFIG REWRITE OK

这样重启后密码不会丢。如果忘了执行CONFIG REWRITE,下次重启密码就回到旧值,这是一个非常典型的“重启后密码失效”原因。

3.6 可视化客户端的密码配置

团队开发时,离不开可视化客户端工具。目前用得比较多的是Redis Desktop Manager(RDM)和Another Redis Desktop Manager(ARDM)。连接配置里填密码的位置很清楚,新建连接窗口中有Password字段,填上密码即可。

如果连接时填了密码还是失败,优先排查三件事:

  • Redis服务器是否真的开启了密码:CONFIG GET requirepass。
  • 网络是否通了:telnet <ip> 6379能连上再谈认证。
  • RDM版本是否支持Redis版本的新命令:老版本RDM在Redis 6.x ACL模式下可能认证不兼容,建议升级到最新版或改用ARDM。

我自己在Windows环境遇到过一次RDM死活连不上、redis-cli却能正常AUTH的情况,最后发现是RDM默认走了SSH隧道,而我的Redis在容器里,本地没有映射端口,属于配置乌龙。开发工具连不上时,先用命令行确认Redis本身没毛病,再排查工具配置,这个顺序能省大量时间。

4. 设置密码后常见报错与排查技巧

4.1 NOAUTH Authentication required

这是设置密码后最常见的报错。出现场景一般是:日常脚本或命令行工具在Redis重启后突然报NOAUTH Authentication required,而你确认密码没改。大概率是Redis加载了配置文件,开启了requirepass,但你的连接工具没有传密码。

排查方法分两步。第一步,用redis-cli -a <密码> ping确认密码正确;第二步,检查业务代码的连接参数是否带了password。以Java的Jedis为例:

Jedis jedis = new Jedis("127.0.0.1", 6379); jedis.auth("YourStrongPassword2024!");

Spring Boot Redis配置中,密码写在配置文件的spring.redis.password字段。Python的redis-py库:

r = redis.Redis(host='127.0.0.1', port=6379, password='YourStrongPassword2024!')

这类问题十有八九是代码或脚本配置问题,不是Redis本身的问题。

4.2 重启后密码莫名失效

前面提到了,CONFIG SET修改的内存配置不会持久化,需要CONFIG REWRITE写入配置文件。还有一种情况是配置文件名不对。Linux上systemd服务默认加载/etc/redis/redis.conf,你如果改了/usr/local/src/redis-7.2/redis.conf,重启服务后加载的是另一个文件,密码自然不生效。

Docker场景下,如果容器启动命令没有指定配置文件位置,--requirepass传参只在启动命令中有效,容器重建后如果换了启动参数,密码也会变。排查这类问题,步骤是:先看进程启动参数或systemd配置文件,确认实际加载了哪个配置文件,再检查这个文件里requirepass是否真的改了。

4.3 主从或哨兵复制断连

主从架构中,只给主节点设置密码、从节点不配masterauth,从节点的日志会不断刷错误,现象是主从状态一直处于down或SYNC失败。哨兵模式下,哨兵节点需要配置sentinel auth-pass,否则哨兵对主节点的健康检查失败,认为主节点挂了,会频繁触发选举切换。

这里提供一个排错小技巧:info replication命令在从节点上能看到master_link_status:down,如果确认网络没问题,优先检查从节点的masterauth和哨兵的auth-pass。另外,主从节点的密码策略要保持一致,如果主节点动态改了密码,从节点必须同步改masterauth并重新执行REPLICAOF触发重新同步。

4.4 密码包含特殊字符的坑

密码里包含!、$、&、空格、#这类特殊字符时,在shell命令行里直接使用redis-cli -a会出问题。比如:

redis-cli -a YourStrongPassword2024!

在bash中,!会触发历史扩展,命令实际执行的密码可能变成YourStrongPassword2024加一条错误信息。更隐蔽的是$符号被变量替换。解决办法是给密码加单引号:

redis-cli -a 'YourStrongPassword2024!'

在配置文件里写密码则没有这个问题,但是要注意redis-cli -a之后的警告信息,它不在配置文件范畴内,主要是命令行传参的明文暴露问题。配置文件中密码如果有空格或特殊字符,直接写就行,但客户端代码中要用URL编码或转义。

4.5 忘记密码后的恢复流程

生产环境偶尔会遇到配置文件里的密码忘了、或者交接时没记录密码的情况。恢复思路是:绕过认证改配置,而不是暴力破解。

第一步,临时停掉Redis。如果是systemd管理:

systemctl stop redis

第二步,用不带认证的方式启动Redis。有两种方式:一种是指定一个不包含requirepass的临时配置文件启动;另一种是直接加--requirepass ""参数重置为空:

redis-server --requirepass ""

但这种方式下Redis启动时仍然会要求从配置文件读取requirepass,所以更稳妥的是用--config-append方式覆盖:

redis-server --port 6380 --requirepass ""

第三步,连接后重新设置密码:

redis-cli -p 6380 127.0.0.1:6380> CONFIG SET requirepass NewPassword2024! 127.0.0.1:6380> CONFIG REWRITE 127.0.0.1:6380> SHUTDOWN NOSAVE

最后正常启动Redis,新密码就生效了。整个过程对数据无损,SHUTDOWN NOSAVE避免内存数据因为突然停机而触发不必要的问题。

4.6 还有几个安全习惯值得养成

设置密码的同时,把下面几个配置也一起检查一遍,安全防线才完整:

  • rename-command CONFIG改成自定义命令名,防止攻击者和普通开发者在拿到连接权限后读取或修改关键配置。
  • rename-command FLUSHALL、rename-command FLUSHDB改成自定义名或直接禁用,避免误操作或恶意清库。
  • rename-command SHUTDOWN改成自定义名,防止攻击者远程关闭Redis。
  • 设置maxmemory和maxmemory-policy,避免缓存写满内存导致系统崩溃。

修改rename-command后,如果业务代码或运维脚本里用了原命令名,必须同步调整,否则会报ERR unknown command。这一点在升级Redis版本或迁移配置时尤其要注意。

5. 一些实用心得

给Redis设置密码这件事,看起来就是改一行配置,但实际落地时牵扯的环节不少:主从要配masterauth、哨兵要配auth-pass、业务代码要带密码连接、可视化工具要填密码、容器启动命令要传参、配置文件要记得CONFIG REWRITE。我自己的习惯是,任何时候新装一个Redis实例,先把requirepass加上,再开始谈业务接入,免得后续改动牵一发动全身。

另外强烈建议把密码统一纳入团队的密钥管理系统,不要散落在各个开发者的本地文档和聊天记录里。Redis的密码不像数据库账号那样有独立权限体系,一旦泄露就意味着缓存数据可读可写,影响面很大。定期更换密码也是值得做的,虽然麻烦,但配合连接池和客户端配置中心使用,切换成本其实不高。

最后再分享一个小技巧:在跑redis-server --test-memory或者做性能压测时,记得把密码参数带上,不然redis-benchmark测出来的结果会先被NOAUTH错误污染,反馈的数据不具备参考价值。这种细节平时不留意,等到了排查性能瓶颈的时候,容易被误导。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询