第九章:安全配置

深入了解 Redis 安全配置,包括认证、ACL、加密连接和网络安全。

最后更新: 2024-01-15
页面目录

Redis 安全配置

安全是生产环境部署的重要考虑因素。本章介绍 Redis 的各种安全配置选项。

安全架构

┌─────────────────────────────────────────────────────────────────┐
│                      Redis 安全架构                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                     网络层安全                          │   │
│   │   • 绑定地址 (bind)                                    │   │
│   │   • 防火墙 (iptables/firewalld)                        │   │
│   │   • TLS/SSL 加密连接                                   │   │
│   └─────────────────────────────────────────────────────────┘   │
│                           │                                     │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                     认证层                               │   │
│   │   • 密码认证 (requirepass)                              │   │
│   │   • ACL 用户权限控制                                    │   │
│   │   • 命令重命名/禁用                                     │   │
│   └─────────────────────────────────────────────────────────┘   │
│                           │                                     │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                     数据层安全                           │   │
│   │   • 数据加密(AES)                                     │   │
│   │   • 数据脱敏                                            │   │
│   │   • 安全审计                                            │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

密码认证

配置密码

# redis.conf
requirepass your_strong_password

# 密码强度建议
# - 至少 32 字符
# - 包含大小写、数字、特殊字符
# - 不使用常见单词

命令行设置

# 启动时设置
redis-server --requirepass password

# 运行时设置
redis-cli CONFIG SET requirepass password

# 查看密码(实际为占位符)
redis-cli CONFIG GET requirepass

连接认证

# 方式一:命令行参数
redis-cli -a password

# 方式二:连接后认证
redis-cli
AUTH password

# 方式三:PING 测试
redis-cli -a password PING

Python 连接

import redis

# 密码认证
client = redis.Redis(
    host='localhost',
    port=6379,
    password='your_password',
    decode_responses=True
)

# 测试连接
client.ping()

ACL 访问控制

Redis 6.0 引入了 ACL(Access Control List)功能,支持细粒度的用户权限控制。

ACL 工作原理

┌─────────────────────────────────────────────────────────────────┐
│                       ACL 权限模型                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                    ACL 用户                            │   │
│   │                                                         │   │
│   │   user alice on >p1... ~cached:* &@all                  │   │
│   │       │        │     │        │    │                   │   │
│   │       │        │     │        │    └── 权限类别        │   │
│   │       │        │     │        │                        │   │
│   │       │        │     │        └── 允许的键模式          │   │
│   │       │        │     │                                  │   │
│   │       │        │     └── 允许的 DSL 编码                │   │
│   │       │        │                                        │   │
│   │       │        └── 密码(SHA-256 哈希)                   │   │
│   │       │                                                   │   │
│   │       └── 启用/禁用                                        │   │
│   │                                                           │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

ACL 命令

# 创建用户
ACL SETUSER alice on '>password' ~cached:* +get +set +del -@all

# 创建只读用户
ACL SETUSER readonly on '>password' ~* -@all +get

# 创建管理员用户
ACL SETUSER admin on '>password' ~* +@all

# 查看用户
ACL LIST

# 查看用户详情
ACL GETUSER alice

# 启用/禁用用户
ACL SETUSER alice off
ACL SETUSER alice on

# 删除用户
ACL DELUSER alice

ACL 权限

权限 说明
+command 允许执行命令
-command 禁止执行命令
+@category 允许某类命令
-@category 禁止某类命令
~patterns 允许的键模式
#password 设置密码
>password 清除密码

命令类别

类别 包含命令
@read GET, HGET, LRANGE 等
@write SET, DEL, LPUSH 等
@admin ADMIN, CONFIG, SHUTDOWN 等
@dangerous FLUSHDB, KEYS, SCRIPT 等
@all 所有命令
@none 无命令权限

ACL 配置示例

# redis.conf
user alice on >argon2_hash ~cached:* +get +set +del +exists ~session:* +get

user readonly on >hash123 ~* -@admin +@read -@dangerous

user admin on >admin456 ~* +@all

user app on >'SHA256-CryptedPassword' ~app:* +get +set +hget +hset +@read +@write

Python ACL 连接

import redis

# 使用 ACL 用户连接
client = redis.Redis(
    host='localhost',
    port=6379,
    username='alice',
    password='password',
    decode_responses=True
)

client.set('cached:user:1', 'value')

命令重命名与禁用

重命名命令

# 命令重命名(增加安全性)
rename-command CONFIG b840fc02d524045429341cc3e480787fac704bfa
rename-command FLUSHDB b840fc02d524045429341cc3e480787fac704bfb
rename-command FLUSHALL b840fc02d524045429341cc3e480787fac704bfc
rename-command KEYS b840fc02d524045429341cc3e480787fac704bfd
rename-command SHUTDOWN ""

安全建议

命令 建议操作
FLUSHDB 重命名为复杂字符串
FLUSHALL 禁用或重命名
KEYS 重命名为复杂字符串
SHUTDOWN 重命名
CONFIG 限制访问
EVAL/EVALSHA 限制执行

网络安全

绑定地址

# 只绑定本地
bind 127.0.0.1

# 绑定内网 IP
bind 127.0.0.1 192.168.1.100

# 保护模式(无绑定且无密码时拒绝外部连接)
protected-mode yes

防火墙配置

# iptables (Linux)
# 允许特定 IP 访问 Redis
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 6379 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP

# firewalld (CentOS)
firewall-cmd --permanent --add-port=6379/tcp
firewall-cmd --permanent --add-source=192.168.1.0/24
firewall-cmd --reload

TLS/SSL 加密

# TLS 配置
tls-port 6380
port 0  # 禁用非 TLS 连接

tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt

# TLS 认证模式
tls-auth-clients no          # 可选:客户端证书认证
tls-auth-clients optional   # 可选:客户端证书认证

生成证书

# 生成私钥
openssl genrsa -out redis.key 2048

# 生成证书请求
openssl req -new -key redis.key -out redis.csr

# 自签名证书
openssl x509 -req -in redis.csr -signkey redis.key -out redis.crt

# CA 证书(如果有)
openssl x509 -req -in redis.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out redis.crt

Docker TLS 配置

services:
  redis:
    image: redis:7-alpine
    ports:
      - "6380:6380"
    volumes:
      - ./tls:/etc/redis/tls
    command: |
      redis-server --port 6380
        --tls-port 6380
        --tls-cert-file /etc/redis/tls/redis.crt
        --tls-key-file /etc/redis/tls/redis.key
        --tls-ca-cert-file /etc/redis/tls/ca.crt
        --tls-auth-clients optional

数据安全

数据加密(应用层)

from cryptography.fernet import Fernet
import redis

# 生成密钥(安全存储)
key = Fernet.generate_key()
cipher = Fernet(key)

# 加密数据
def encrypt_data(data):
    return cipher.encrypt(data.encode())

def decrypt_data(encrypted_data):
    return cipher.decrypt(encrypted_data).decode()

# Redis 操作
client = redis.Redis(host='localhost', port=6379, password='pwd')

# 存储加密数据
encrypted = encrypt_data("sensitive data")
client.set('key', encrypted)

# 读取解密数据
encrypted = client.get('key')
decrypted = decrypt_data(encrypted)

数据脱敏

def mask_phone(phone):
    """手机号脱敏:138****1234"""
    if len(phone) == 11:
        return phone[:3] + '****' + phone[-4:]
    return phone

def mask_id_card(id_card):
    """身份证脱敏:320***********1234"""
    if len(id_card) == 18:
        return id_card[:3] + '*' * 11 + id_card[-4:]
    return id_card

# 存储时脱敏
masked_phone = mask_phone("13812341234")
client.hset('user:1', 'phone', masked_phone)

安全审计

开启命令日志

# 命令日志
slowlog-log-slower-than 0  # 记录所有命令
slowlog-max-len 10000

# 或使用 Redis 审计插件
# RedisGears, RedisGrove 等

Lua 脚本安全

# 限制 Lua 脚本执行
# 配置最大内存和执行时间
lua-time-limit 5000

# 沙箱限制
# Lua 脚本只能访问有限的功能

监控脚本

#!/usr/bin/env python3
import redis
import json
import logging
from datetime import datetime

class RedisSecurityMonitor:
    def __init__(self):
        self.client = redis.Redis(host='localhost', port=6379, 
                                  password='pwd', decode_responses=True)
        self.logger = logging.getLogger('security')
    
    def check_failed_auth(self):
        """检查认证失败"""
        info = self.client.info('clients')
        # 检查 clients_clipped 或其他指标
        pass
    
    def scan_dangerous_keys(self):
        """扫描危险键"""
        dangerous = []
        for key in self.client.scan_iter('*'):
            # 检查异常键名
            if any(x in key.lower() for x in ['admin', 'password', 'secret']):
                dangerous.append(key)
        return dangerous
    
    def audit_access(self):
        """审计访问"""
        # 记录访问日志
        pass

if __name__ == '__main__':
    monitor = RedisSecurityMonitor()
    dangerous = monitor.scan_dangerous_keys()
    if dangerous:
        print(f"发现敏感键: {dangerous}")

生产环境安全配置

# 生产环境推荐配置
# /etc/redis/production.conf

# 网络安全
bind 127.0.0.1 <internal_ip>
protected-mode yes
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 300

# 密码认证
requirepass <strong_password>

# ACL
user default on nopass ~* &* +@all

# 命令限制
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS "8b7c92a1f0d3e4f5"
rename-command SHUTDOWN "7h9k0m1n2b3v4c5"

# 日志
loglevel notice
logfile /var/log/redis/redis.log

# 内存
maxmemory 4gb
maxmemory-policy allkeys-lru

# 持久化
save 900 1
save 300 10
save 60 10000

# AOF
appendonly yes
appendfsync everysec

安全检查清单

┌─────────────────────────────────────────────────────────────────┐
│                   Redis 安全检查清单                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  网络安全:                                                        │
│  □ bind 只绑定必要地址                                           │
│  □ protected-mode 启用                                          │
│  □ 防火墙限制访问                                                 │
│  □ 生产环境启用 TLS                                              │
│                                                                  │
│  认证授权:                                                        │
│  □ 设置强密码                                                     │
│  □ 使用 ACL 细粒度控制                                           │
│  □ 禁用或重命名危险命令                                           │
│  □ 定期轮换密码                                                   │
│                                                                  │
│  数据安全:                                                        │
│  □ 敏感数据加密存储                                               │
│  □ 数据脱敏处理                                                   │
│  □ 定期备份                                                       │
│                                                                  │
│  监控审计:                                                        │
│  □ 开启慢查询日志                                                 │
│  □ 监控异常访问                                                   │
│  □ 记录审计日志                                                   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

下一步

接下来让我们学习 Redis 性能优化。

👉 性能优化