08-27-周三_17-09-29

This commit is contained in:
2025-08-27 17:10:05 +08:00
commit 86df397d8f
12735 changed files with 1145479 additions and 0 deletions

View File

@@ -0,0 +1,784 @@
# Redis 安全管理
## 访问控制
### 密码认证
Redis 提供了基本的密码认证机制来保护数据安全。
**配置密码认证**
```shell
# 在配置文件中设置密码
# /etc/redis/redis.conf
requirepass your_strong_password
# 动态设置密码
redis-cli CONFIG SET requirepass "your_strong_password"
# 使用密码连接
redis-cli -a your_strong_password
# 或者连接后认证
redis-cli
127.0.0.1:6379> AUTH your_strong_password
OK
```
**密码安全最佳实践**
```shell
# 生成强密码
openssl rand -base64 32
# 密码复杂度要求:
# - 长度至少16位
# - 包含大小写字母、数字、特殊字符
# - 避免使用字典词汇
# - 定期更换密码
# 示例强密码
requirepass "Rd!s@2024#Str0ng&P@ssw0rd"
```
### 用户管理 (ACL)
Redis 6.0+ 引入了 ACLAccess Control List功能提供更细粒度的权限控制。
**ACL 基本概念**
```shell
# 查看当前用户
ACL WHOAMI
# 列出所有用户
ACL LIST
# 查看用户详细信息
ACL GETUSER username
# 查看当前用户权限
ACL GETUSER default
```
**创建和管理用户**
```shell
# 创建只读用户
ACL SETUSER readonly on >readonly_password ~* &* -@all +@read
# 创建读写用户(限制特定键模式)
ACL SETUSER readwrite on >readwrite_password ~app:* &* -@all +@read +@write
# 创建管理员用户
ACL SETUSER admin on >admin_password ~* &* +@all
# 创建应用用户(限制命令)
ACL SETUSER appuser on >app_password ~app:* &* -@all +get +set +del +exists +expire
# 删除用户
ACL DELUSER username
```
**ACL 规则详解**
```shell
# ACL 规则语法:
# on/off启用/禁用用户
# >password设置密码
# ~pattern允许访问的键模式
# &pattern允许访问的发布订阅频道模式
# +command允许的命令
# -command禁止的命令
# +@category允许的命令分类
# -@category禁止的命令分类
# 常用命令分类:
# @read读命令
# @write写命令
# @admin管理命令
# @dangerous危险命令
# @keyspace键空间命令
# @string字符串命令
# @list列表命令
# @set集合命令
# @hash哈希命令
# @sortedset有序集合命令
```
### 权限控制
**细粒度权限配置**
```shell
# 数据库管理员
ACL SETUSER dba on >dba_password ~* &* +@all
# 应用开发者
ACL SETUSER developer on >dev_password ~dev:* &dev:* -@all +@read +@write -flushdb -flushall -shutdown
# 监控用户
ACL SETUSER monitor on >monitor_password ~* &* -@all +info +ping +client +config|get
# 备份用户
ACL SETUSER backup on >backup_password ~* &* -@all +@read +bgsave +lastsave
# 只读分析用户
ACL SETUSER analyst on >analyst_password ~analytics:* &* -@all +@read +scan +keys
```
**权限验证测试**
```shell
# 测试用户权限
redis-cli --user readonly --pass readonly_password
127.0.0.1:6379> GET some_key # 应该成功
127.0.0.1:6379> SET some_key value # 应该失败
# 测试键模式限制
redis-cli --user developer --pass dev_password
127.0.0.1:6379> GET dev:config # 应该成功
127.0.0.1:6379> GET prod:config # 应该失败
```
### IP 白名单
**网络访问控制**
```shell
# 绑定特定IP地址
# /etc/redis/redis.conf
bind 127.0.0.1 192.168.1.100 10.0.0.50
# 禁用保护模式(仅在安全网络环境中)
protected-mode no
# 使用防火墙限制访问
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
```
## 网络安全
### 端口安全
**端口配置和保护**
```shell
# 更改默认端口
# /etc/redis/redis.conf
port 16379 # 使用非标准端口
# 禁用端口仅使用Unix套接字
port 0
unixsocket /var/run/redis/redis.sock
unixsocketperm 700
# 连接Unix套接字
redis-cli -s /var/run/redis/redis.sock
```
**网络接口绑定**
```shell
# 仅绑定内网接口
bind 127.0.0.1 192.168.1.100
# 绑定多个接口
bind 127.0.0.1 10.0.0.100 172.16.0.100
# 监听所有接口(不推荐)
# bind 0.0.0.0
```
### SSL/TLS 加密
Redis 6.0+ 支持 SSL/TLS 加密传输。
**生成SSL证书**
```shell
# 创建证书目录
sudo mkdir -p /etc/redis/ssl
cd /etc/redis/ssl
# 生成私钥
sudo openssl genrsa -out redis.key 2048
# 生成证书签名请求
sudo openssl req -new -key redis.key -out redis.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=Company/CN=redis.example.com"
# 生成自签名证书
sudo openssl x509 -req -days 365 -in redis.csr -signkey redis.key -out redis.crt
# 生成DH参数文件
sudo openssl dhparam -out redis.dh 2048
# 设置权限
sudo chown redis:redis /etc/redis/ssl/*
sudo chmod 600 /etc/redis/ssl/redis.key
sudo chmod 644 /etc/redis/ssl/redis.crt
sudo chmod 644 /etc/redis/ssl/redis.dh
```
**配置SSL/TLS**
```shell
# Redis 配置文件
# /etc/redis/redis.conf
# 启用TLS端口
port 0
tls-port 6380
# 证书文件路径
tls-cert-file /etc/redis/ssl/redis.crt
tls-key-file /etc/redis/ssl/redis.key
tls-dh-params-file /etc/redis/ssl/redis.dh
# CA证书如果使用
# tls-ca-cert-file /etc/redis/ssl/ca.crt
# 客户端证书验证
tls-auth-clients yes
# TLS协议版本
tls-protocols "TLSv1.2 TLSv1.3"
# 密码套件
tls-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
tls-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
# 会话缓存
tls-session-caching no
tls-session-cache-size 5000
tls-session-cache-timeout 60
```
**SSL客户端连接**
```shell
# 使用SSL连接
redis-cli --tls --cert /etc/redis/ssl/client.crt --key /etc/redis/ssl/client.key --cacert /etc/redis/ssl/ca.crt -p 6380
# 跳过证书验证(仅测试环境)
redis-cli --tls --insecure -p 6380
```
### 防火墙配置
**iptables 配置**
```shell
# 允许特定IP访问Redis
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 6379 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6379 -j DROP
# 限制连接频率
sudo iptables -A INPUT -p tcp --dport 6379 -m connlimit --connlimit-above 10 -j DROP
sudo iptables -A INPUT -p tcp --dport 6379 -m recent --set --name redis
sudo iptables -A INPUT -p tcp --dport 6379 -m recent --update --seconds 60 --hitcount 20 --name redis -j DROP
# 保存规则
sudo iptables-save > /etc/iptables/rules.v4
```
**UFW 配置**
```shell
# 启用UFW
sudo ufw enable
# 允许SSH
sudo ufw allow ssh
# 允许特定网络访问Redis
sudo ufw allow from 192.168.1.0/24 to any port 6379
# 拒绝其他Redis连接
sudo ufw deny 6379
# 查看规则
sudo ufw status numbered
```
### VPN 访问
**OpenVPN 配置示例**
```shell
# 安装OpenVPN
sudo apt update
sudo apt install openvpn easy-rsa
# 配置VPN服务器
sudo make-cadir /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa
# 初始化PKI
./easyrsa init-pki
./easyrsa build-ca
./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-dh
# 生成客户端证书
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1
```
## 数据安全
### 数据加密
**应用层加密**
```python
# Python 数据加密示例
import redis
import json
from cryptography.fernet import Fernet
class EncryptedRedis:
def __init__(self, host='localhost', port=6379, password=None, key=None):
self.redis = redis.Redis(host=host, port=port, password=password)
self.cipher = Fernet(key or Fernet.generate_key())
def set(self, name, value, ex=None):
"""加密存储数据"""
if isinstance(value, dict):
value = json.dumps(value)
encrypted_value = self.cipher.encrypt(value.encode())
return self.redis.set(name, encrypted_value, ex=ex)
def get(self, name):
"""解密获取数据"""
encrypted_value = self.redis.get(name)
if encrypted_value:
decrypted_value = self.cipher.decrypt(encrypted_value)
return decrypted_value.decode()
return None
def hset(self, name, key, value):
"""加密存储哈希字段"""
if isinstance(value, dict):
value = json.dumps(value)
encrypted_value = self.cipher.encrypt(value.encode())
return self.redis.hset(name, key, encrypted_value)
def hget(self, name, key):
"""解密获取哈希字段"""
encrypted_value = self.redis.hget(name, key)
if encrypted_value:
decrypted_value = self.cipher.decrypt(encrypted_value)
return decrypted_value.decode()
return None
# 使用示例
key = Fernet.generate_key()
encrypted_redis = EncryptedRedis(password='your_password', key=key)
# 存储加密数据
user_data = {'name': 'John', 'email': 'john@example.com', 'phone': '123-456-7890'}
encrypted_redis.set('user:1', json.dumps(user_data))
# 获取解密数据
data = encrypted_redis.get('user:1')
user_info = json.loads(data)
print(user_info)
```
### 敏感数据处理
**敏感数据脱敏**
```python
# 数据脱敏工具
import re
import hashlib
class DataMasking:
@staticmethod
def mask_phone(phone):
"""手机号脱敏"""
if len(phone) == 11:
return phone[:3] + '****' + phone[7:]
return phone
@staticmethod
def mask_email(email):
"""邮箱脱敏"""
if '@' in email:
local, domain = email.split('@')
if len(local) > 2:
masked_local = local[0] + '*' * (len(local) - 2) + local[-1]
else:
masked_local = '*' * len(local)
return f"{masked_local}@{domain}"
return email
@staticmethod
def mask_id_card(id_card):
"""身份证脱敏"""
if len(id_card) == 18:
return id_card[:6] + '********' + id_card[14:]
return id_card
@staticmethod
def hash_sensitive_data(data, salt=''):
"""敏感数据哈希"""
return hashlib.sha256((str(data) + salt).encode()).hexdigest()
# 使用示例
masker = DataMasking()
# 存储脱敏数据
user_data = {
'name': 'John Doe',
'phone': masker.mask_phone('13812345678'),
'email': masker.mask_email('john.doe@example.com'),
'id_card': masker.mask_id_card('110101199001011234')
}
redis_client = redis.Redis(password='your_password')
redis_client.hset('user:masked:1', mapping=user_data)
```
### 备份安全
**安全备份策略**
```shell
#!/bin/bash
# 安全备份脚本
BACKUP_DIR="/secure/backup/redis"
ENCRYPTION_KEY="/secure/keys/backup.key"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="redis_backup_$DATE.rdb"
ENCRYPTED_FILE="$BACKUP_FILE.enc"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 生成备份
redis-cli --rdb $BACKUP_DIR/$BACKUP_FILE
# 加密备份文件
openssl enc -aes-256-cbc -salt -in $BACKUP_DIR/$BACKUP_FILE -out $BACKUP_DIR/$ENCRYPTED_FILE -pass file:$ENCRYPTION_KEY
# 删除未加密文件
rm $BACKUP_DIR/$BACKUP_FILE
# 计算校验和
sha256sum $BACKUP_DIR/$ENCRYPTED_FILE > $BACKUP_DIR/$ENCRYPTED_FILE.sha256
# 设置权限
chmod 600 $BACKUP_DIR/$ENCRYPTED_FILE
chown backup:backup $BACKUP_DIR/$ENCRYPTED_FILE
echo "备份完成:$BACKUP_DIR/$ENCRYPTED_FILE"
# 清理旧备份保留30天
find $BACKUP_DIR -name "*.enc" -mtime +30 -delete
find $BACKUP_DIR -name "*.sha256" -mtime +30 -delete
```
**备份恢复脚本**
```shell
#!/bin/bash
# 安全恢复脚本
BACKUP_FILE="$1"
ENCRYPTION_KEY="/secure/keys/backup.key"
TEMP_DIR="/tmp/redis_restore"
if [ -z "$BACKUP_FILE" ]; then
echo "用法: $0 <encrypted_backup_file>"
exit 1
fi
# 验证文件存在
if [ ! -f "$BACKUP_FILE" ]; then
echo "备份文件不存在: $BACKUP_FILE"
exit 1
fi
# 验证校验和
if [ -f "$BACKUP_FILE.sha256" ]; then
echo "验证文件完整性..."
sha256sum -c "$BACKUP_FILE.sha256"
if [ $? -ne 0 ]; then
echo "文件完整性验证失败"
exit 1
fi
fi
# 创建临时目录
mkdir -p $TEMP_DIR
# 解密备份文件
echo "解密备份文件..."
DECRYPTED_FILE="$TEMP_DIR/$(basename $BACKUP_FILE .enc)"
openssl enc -aes-256-cbc -d -in "$BACKUP_FILE" -out "$DECRYPTED_FILE" -pass file:$ENCRYPTION_KEY
if [ $? -eq 0 ]; then
echo "备份文件已解密到: $DECRYPTED_FILE"
echo "请手动将文件复制到Redis数据目录并重启服务"
else
echo "解密失败"
rm -rf $TEMP_DIR
exit 1
fi
```
### 审计日志
**审计日志配置**
```shell
# Redis 配置文件
# /etc/redis/redis.conf
# 启用命令日志
logfile /var/log/redis/redis-server.log
loglevel notice
# 启用慢查询日志
slowlog-log-slower-than 10000
slowlog-max-len 128
# 客户端连接日志
# 通过监控脚本实现
```
**审计日志脚本**
```shell
#!/bin/bash
# Redis 审计日志脚本
LOG_FILE="/var/log/redis/audit.log"
REDIS_LOG="/var/log/redis/redis-server.log"
# 监控Redis连接
tail -f $REDIS_LOG | while read line; do
if echo "$line" | grep -q "Accepted\|Client closed connection"; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $line" >> $LOG_FILE
fi
done &
# 监控命令执行需要启用monitor
redis-cli monitor | while read line; do
# 过滤敏感命令
if echo "$line" | grep -qE "AUTH|CONFIG|EVAL|FLUSHDB|FLUSHALL|SHUTDOWN"; then
echo "$(date '+%Y-%m-%d %H:%M:%S') SENSITIVE: $line" >> $LOG_FILE
fi
done &
echo "审计日志监控已启动"
```
## 安全最佳实践
### 安全配置检查
**安全配置检查清单**
```shell
#!/bin/bash
# Redis 安全配置检查脚本
echo "=== Redis 安全配置检查 ==="
# 检查密码配置
echo "1. 检查密码配置"
if redis-cli CONFIG GET requirepass | grep -q "requirepass"; then
echo "✓ 已配置密码认证"
else
echo "✗ 未配置密码认证"
fi
# 检查绑定地址
echo "2. 检查绑定地址"
BIND_ADDR=$(redis-cli CONFIG GET bind | tail -1)
if [ "$BIND_ADDR" != "" ] && [ "$BIND_ADDR" != "0.0.0.0" ]; then
echo "✓ 绑定地址配置安全: $BIND_ADDR"
else
echo "✗ 绑定地址不安全: $BIND_ADDR"
fi
# 检查保护模式
echo "3. 检查保护模式"
PROTECTED_MODE=$(redis-cli CONFIG GET protected-mode | tail -1)
if [ "$PROTECTED_MODE" = "yes" ]; then
echo "✓ 保护模式已启用"
else
echo "✗ 保护模式未启用"
fi
# 检查危险命令
echo "4. 检查危险命令"
DANGEROUS_COMMANDS=("FLUSHDB" "FLUSHALL" "CONFIG" "EVAL" "SHUTDOWN" "DEBUG")
for cmd in "${DANGEROUS_COMMANDS[@]}"; do
if redis-cli CONFIG GET "rename-command" | grep -q "$cmd"; then
echo "✓ 危险命令 $cmd 已重命名或禁用"
else
echo "✗ 危险命令 $cmd 未处理"
fi
done
# 检查文件权限
echo "5. 检查文件权限"
REDIS_CONF="/etc/redis/redis.conf"
if [ -f "$REDIS_CONF" ]; then
PERM=$(stat -c "%a" "$REDIS_CONF")
if [ "$PERM" = "640" ] || [ "$PERM" = "600" ]; then
echo "✓ 配置文件权限安全: $PERM"
else
echo "✗ 配置文件权限不安全: $PERM"
fi
fi
# 检查日志配置
echo "6. 检查日志配置"
LOGFILE=$(redis-cli CONFIG GET logfile | tail -1)
if [ "$LOGFILE" != "" ]; then
echo "✓ 已配置日志文件: $LOGFILE"
else
echo "✗ 未配置日志文件"
fi
echo "=== 检查完成 ==="
```
### 漏洞防护
**常见漏洞防护措施**
```shell
# 1. 禁用或重命名危险命令
# /etc/redis/redis.conf
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG "CONFIG_b840fc02d524045429941cc15f59e41cb7be6c52"
rename-command EVAL ""
rename-command DEBUG ""
rename-command SHUTDOWN "SHUTDOWN_b840fc02d524045429941cc15f59e41cb7be6c52"
# 2. 限制客户端连接
maxclients 1000
timeout 300
tcp-keepalive 300
# 3. 禁用Lua脚本调试
lua-replicate-commands yes
# 4. 设置内存限制
maxmemory 2gb
maxmemory-policy allkeys-lru
```
### 安全更新
**安全更新策略**
```shell
#!/bin/bash
# Redis 安全更新脚本
echo "检查Redis版本和安全更新"
# 获取当前版本
CURRENT_VERSION=$(redis-server --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
echo "当前Redis版本: $CURRENT_VERSION"
# 检查是否有安全更新
echo "检查安全公告..."
echo "请访问以下链接查看最新安全公告:"
echo "- https://redis.io/topics/security"
echo "- https://github.com/redis/redis/security/advisories"
# 备份当前配置
echo "备份当前配置..."
cp /etc/redis/redis.conf /etc/redis/redis.conf.backup.$(date +%Y%m%d)
# 更新前检查
echo "更新前安全检查:"
redis-cli CONFIG GET '*' > /tmp/redis_config_before_update.txt
echo "请手动执行以下步骤:"
echo "1. 下载最新稳定版本"
echo "2. 测试环境验证"
echo "3. 制定回滚计划"
echo "4. 执行更新"
echo "5. 验证功能和安全配置"
```
### 应急响应
**安全事件应急响应**
```shell
#!/bin/bash
# Redis 安全事件应急响应脚本
INCIDENT_LOG="/var/log/redis/security_incident.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "=== Redis 安全事件应急响应 ==="
echo "事件时间: $DATE" | tee -a $INCIDENT_LOG
# 1. 立即隔离
echo "1. 立即隔离Redis服务"
echo "停止Redis服务? (y/n)"
read -r response
if [ "$response" = "y" ]; then
sudo systemctl stop redis
echo "$DATE: Redis服务已停止" | tee -a $INCIDENT_LOG
fi
# 2. 收集证据
echo "2. 收集安全证据"
EVIDENCE_DIR="/tmp/redis_incident_$(date +%Y%m%d_%H%M%S)"
mkdir -p $EVIDENCE_DIR
# 收集日志
cp /var/log/redis/* $EVIDENCE_DIR/ 2>/dev/null
# 收集配置
cp /etc/redis/redis.conf $EVIDENCE_DIR/
# 收集进程信息
ps aux | grep redis > $EVIDENCE_DIR/processes.txt
# 收集网络连接
netstat -tulpn | grep :6379 > $EVIDENCE_DIR/connections.txt
# 收集系统信息
uname -a > $EVIDENCE_DIR/system_info.txt
whoami > $EVIDENCE_DIR/current_user.txt
echo "证据已收集到: $EVIDENCE_DIR"
echo "$DATE: 证据收集完成 - $EVIDENCE_DIR" | tee -a $INCIDENT_LOG
# 3. 分析威胁
echo "3. 分析潜在威胁"
echo "检查可疑连接..."
redis-cli CLIENT LIST > $EVIDENCE_DIR/client_list.txt 2>/dev/null
echo "检查慢查询日志..."
redis-cli SLOWLOG GET 100 > $EVIDENCE_DIR/slowlog.txt 2>/dev/null
# 4. 修复建议
echo "4. 安全修复建议:"
echo "- 更改Redis密码"
echo "- 检查ACL配置"
echo "- 更新防火墙规则"
echo "- 检查系统用户账户"
echo "- 扫描恶意软件"
echo "- 更新Redis到最新版本"
echo "应急响应完成,详细日志: $INCIDENT_LOG"
```