Redis 完全指南 / 14 - 安全
安全
14.1 安全概述
Redis 默认配置不安全——无密码、绑定所有接口、暴露危险命令。生产环境必须加固。
安全检查清单
| 检查项 | 说明 | 优先级 |
|---|---|---|
| 设置密码 | requirepass / ACL | 🔴 高 |
| 绑定地址 | bind 127.0.0.1 | 🔴 高 |
| 禁用危险命令 | rename-command | 🔴 高 |
| 开启 TLS | 加密传输 | 🟡 中 |
| 使用 ACL | 细粒度权限控制 | 🟡 中 |
| 禁用 CONFIG 命令 | 防止运行时修改配置 | 🟡 中 |
| 定期更新版本 | 修复安全漏洞 | 🟢 低 |
14.2 密码认证
单密码认证(Redis 6.0 之前)
# redis.conf
requirepass YourStr0ngP@ssword
# 方式一:连接时指定密码
redis-cli -a YourStr0ngP@ssword
# 方式二:连接后认证
redis-cli
AUTH YourStr0ngP@ssword
# 方式三:通过命令行参数
redis-cli --pass YourStr0ngP@ssword
⚠️ 安全警告:密码通过明文传输(除非使用 TLS)。在生产环境中,密码可能会出现在 ps 命令和日志中。
主从复制密码
# 从节点配置
masterauth YourStr0ngP@ssword
Sentinel 密码
# sentinel.conf
sentinel auth-pass mymaster YourStr0ngP@ssword
14.3 ACL(访问控制列表)
Redis 6.0 引入了 ACL 系统,支持细粒度的用户权限控制。
ACL 基本概念
┌──────────────────────────────────────┐
│ ACL 用户 │
├──────────────────────────────────────┤
│ 用户名 │ unique string │
│ 密码 │ ≥ 1 个密码 │
│ 命令权限 │ +GET +SET -FLUSHALL ... │
│ Key 权限 │ ~user:* ~cache:* │
│ Channel │ &channel:* │
│ 默认数据库 │ on >password ~* &* │
└──────────────────────────────────────┘
ACL 命令
# 查看所有用户
ACL LIST
# 1) "user default on #<hash> ~* &* +@all"
# 查看当前用户
ACL WHOAMI
# 创建用户
ACL SETUSER appuser on >password123 ~user:* ~cache:* +@read +@write -@admin
# 创建只读用户
ACL SETUSER readonly on >readonly123 ~* +@read
# 创建管理员
ACL SETUSER admin on >admin123 ~* &* +@all
# 禁用用户
ACL SETUSER appuser off
# 删除用户
ACL DELUSER appuser
# 查看用户详情
ACL GETUSER appuser
# 保存 ACL 配置到文件
ACL SAVE
# 加载 ACL 配置
ACL LOAD
ACL 权限类别
| 类别 | 包含的命令 | 说明 |
|---|---|---|
@all | 所有命令 | 全部权限 |
@read | GET, LRANGE, HGET, … | 读命令 |
@write | SET, LPUSH, HSET, … | 写命令 |
@set | SADD, SREM, SMEMBERS, … | Set 操作 |
@sortedset | ZADD, ZRANGE, ZSCORE, … | ZSet 操作 |
@hash | HSET, HGET, HGETALL, … | Hash 操作 |
@list | LPUSH, RPUSH, LRANGE, … | List 操作 |
@string | SET, GET, APPEND, … | String 操作 |
@admin | ACL, CONFIG, DEBUG, … | 管理命令 |
@dangerous | FLUSHALL, FLUSHDB, DEBUG, KEYS | 危险命令 |
@connection | AUTH, PING, QUIT, … | 连接命令 |
@pubsub | PUBLISH, SUBSCRIBE, … | 发布订阅 |
@scripting | EVAL, EVALSHA, … | Lua 脚本 |
@geo | GEOADD, GEODIST, … | 地理位置 |
@hyperloglog | PFADD, PFCOUNT, … | HyperLogLog |
@stream | XADD, XREAD, XREADGROUP, … | Stream |
@slow | KEYS, SORT, … | 慢命令 |
@fast | GET, SET, INCR, … | 快命令 |
ACL 配置文件
# acl.conf
user default on >YourStr0ngP@ssword ~* &* +@all
user app on >apppassword ~app:* +@read +@write -@admin -@dangerous
user readonly on >readpassword ~* +@read
user admin on >adminpassword ~* &* +@all
# 加载 ACL 文件
redis-server --aclfile /etc/redis/acl.conf
ACL 使用示例
# 应用程序用户(只能操作 app:* 前缀的 Key)
ACL SETUSER appuser on >apppass123 ~app:* +@read +@write -@admin -@dangerous
# 切换到 appuser
AUTH appuser apppass123
# ✅ 允许
SET app:config "value"
GET app:config
HSET app:user:1001 name "张三"
# ❌ 禁止(权限不足)
SET other:key "value" # (error) NOPERM
FLUSHALL # (error) NOPERM
CONFIG SET maxmemory 4gb # (error) NOPERM
14.4 rename-command(命令重命名)
Redis 6.0 之前常用的安全措施,通过重命名或禁用危险命令:
# redis.conf
# 禁用 FLUSHALL(设置为空字符串)
rename-command FLUSHALL ""
# 禁用 FLUSHDB
rename-command FLUSHDB ""
# 禁用 DEBUG
rename-command DEBUG ""
# 重命名 CONFIG(只有知道新名称的人才能执行)
rename-command CONFIG CONFIG_b7a2c4d8
# 重命名 KEYS
rename-command KEYS KEYS_b7a2c4d8
⚠️ 注意:Redis 6.0+ 推荐使用 ACL 替代 rename-command,更灵活、更安全。
14.5 TLS 加密
Redis 6.0 支持 TLS 加密传输。
生成证书
# 生成 CA 证书
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -sha256 -key ca.key -days 3650 -out ca.crt -subj "/CN=Redis CA"
# 生成服务器证书
openssl genrsa -out redis-server.key 2048
openssl req -new -sha256 -key redis-server.key -out redis-server.csr -subj "/CN=redis-server"
openssl x509 -req -sha256 -in redis-server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out redis-server.crt -days 365
# 生成客户端证书
openssl genrsa -out redis-client.key 2048
openssl req -new -sha256 -key redis-client.key -out redis-client.csr -subj "/CN=redis-client"
openssl x509 -req -sha256 -in redis-client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out redis-client.crt -days 365
TLS 配置
# redis.conf
# TLS 端口
tls-port 6380
# 禁用非 TLS 端口
port 0
# 证书文件
tls-cert-file /etc/redis/tls/redis-server.crt
tls-key-file /etc/redis/tls/redis-server.key
tls-ca-cert-file /etc/redis/tls/ca.crt
# 客户端证书验证
tls-auth-clients yes
# 主从复制 TLS
tls-replication yes
# 集群总线 TLS
tls-cluster yes
TLS 连接
# 客户端 TLS 连接
redis-cli --tls \
--cert /etc/redis/tls/redis-client.crt \
--key /etc/redis/tls/redis-client.key \
--cacert /etc/redis/tls/ca.crt \
-p 6380
14.6 网络安全
绑定地址
# 只允许本地访问
bind 127.0.0.1 -::1
# 允许特定网段访问
bind 127.0.0.1 192.168.1.0/24
防火墙配置
# UFW (Ubuntu)
sudo ufw allow from 192.168.1.0/24 to any port 6379
sudo ufw allow from 192.168.1.0/24 to any port 26379 # Sentinel
sudo ufw allow from 192.168.1.0/24 to any port 16379 # Cluster bus
# firewalld (CentOS)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="6379" accept'
sudo firewall-cmd --reload
# iptables
sudo iptables -A INPUT -p tcp --dport 6379 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6379 -j DROP
保护模式
# 当 bind 和 requirepass 都未设置时,保护模式会阻止外部访问
protected-mode yes
14.7 运行时安全加固
# 禁用 CONFIG 命令(重命名)
redis-cli CONFIG SET requirepass "new_strong_password"
# 或在配置文件中
rename-command CONFIG ""
# 限制客户端连接数
redis-cli CONFIG SET maxclients 1000
# 禁用危险命令
redis-cli ACL SETUSER default on >password ~* &* +@all -@dangerous
📌 业务场景
场景一:多租户权限隔离
# 租户 A 只能访问 tenant:a:* 前缀
ACL SETUSER tenant_a on >pass_a ~tenant:a:* +@read +@write -@admin
# 租户 B 只能访问 tenant:b:* 前缀
ACL SETUSER tenant_b on >pass_b ~tenant:b:* +@read +@write -@admin
场景二:运维只读权限
ACL SETUSER ops_readonly on >ops_pass ~* +@read +@slow +@admin -@dangerous
场景三:加密传输(跨机房)
# 使用 TLS 加密跨机房的主从复制和客户端连接