Redis Security¶
Redis is not designed to be a secure database It was built for speed in trusted environments where the database server is isolated on a private network with no public exposure. The protocol is simple (text-based, no built-in encryption), authentication was bolted on as an afterthought, and many commands can trivially compromise the entire server if an attacker gets any kind of access
The reality is that Redis will end up on a shared network, some developer will expose it to the internet for "just a quick test," and automated scanners will find it within hours
Authentication - legacy AUTH vs modern ACLs¶
Legacy password (pre-6.0)¶
The old requirepass method gives every connection the same password with the same unlimited permissions. It's better than nothing but provides zero granularity
# redis.conf - legacy auth
requirepass your_very_long_random_password_here
# Minimum: 32 characters of entropy
# Use: openssl rand -base64 48
# Connecting with password
redis-cli -a "your_password"
# Or after connecting:
# AUTH your_password
ACL-based access (Redis 6.0+)¶
ACLs let you create users with specific command permissions and key-pattern access. This is the production-grade approach - your cache service doesn't need CONFIG and your analytics script doesn't need FLUSHALL
# redis.conf - enable ACL
aclfile /etc/redis/users.acl
# /etc/redis/users.acl - define users with granular permissions
# Default user - disabled for security
user default off
# Application user - can only access keys matching "app:*"
# Can run basic commands: GET, SET, DEL, EXPIRE, INCR, TTL, EXISTS
user app_service on >app_secure_password_2024 ~app:* +@read +@write +@set -@dangerous
# Cache service - limited to cache operations
user cache_service on >cache_pwd_here ~cache:* +get +set +del +expire +ttl +exists
# Admin user - full access (only for运维)
user admin on >admin_password_here ~* +@all
# Analytics - read-only access to analytics keys
user analytics on >analytics_pwd ~analytics:* +get +mget +exists +ttl +keys +type
# Rate limiter - only INCR, EXPIRE, TTL on rate limit keys
user ratelimit on >ratelimit_pwd ~ratelimit:* +incr +expire +ttl +get +del
# Managing ACLs via redis-cli
ACL LIST # Show all users
ACL GETUSER app_service # Show specific user permissions
ACL SETUSER temp_user >temp_pwd +get +set ~temp:* # Create temporary user
ACL DELUSER temp_user # Remove user
ACL LOG # View ACL denial logs
TLS for Redis¶
Redis does not encrypt connections by default. Every command and response travels in plaintext over the network. Anyone with packet capture access on the network path can read your cached data, session tokens, and even your authentication password
# redis.conf - enable TLS (Redis 6.0+)
tls-port 6379
port 0 # Disable plaintext port entirely
tls-cert-file /etc/ssl/certs/redis.crt
tls-key-file /etc/ssl/private/redis.key
tls-ca-cert-file /etc/ssl/certs/ca.crt
tls-auth-clients yes # Mutual TLS (client must present cert)
tls-protocols "TLSv1.2 TLSv1.3"
tls-ciphers "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"
// Node.js ioredis - TLS connection
const Redis = require('ioredis');
const redis = new Redis({
host: 'redis.internal.example.com',
port: 6379,
tls: {
key: fs.readFileSync('./client.key'),
cert: fs.readFileSync('./client.crt'),
ca: [fs.readFileSync('./ca.crt')],
rejectUnauthorized: true
},
username: 'app_service',
password: 'app_secure_password_2024'
});
Dangerous commands and their mitigations¶
Some Redis commands are extremely destructive in the wrong hands. FLUSHALL deletes every key in every database. CONFIG SET changes server configuration at runtime. EVAL executes arbitrary Lua scripts. DEBUG SEGFAULT crashes the server
# Strategy 1: rename commands to disabled (empty string = disable)
rename-command FLUSHALL "" # Completely disabled
rename-command FLUSHDB "" # Completely disabled
rename-command CONFIG "" # Completely disabled
rename-command DEBUG "" # Completely disabled
rename-command EVAL "" # Disable Lua scripting if not needed
rename-command SHUTDOWN "" # Prevent remote shutdown
# Strategy 2: rename to obscure names (not security , just obscurity)
rename-command FLUSHALL "ff1a2b3c4d5e6f7a8b9c0d"
rename-command DEBUG "dbg_a1b2c3d4"
# Strategy 3: use ACLs to restrict who can run dangerous commands
# In users.acl:
# user app_service on >password ~app:* +@read +@write -@dangerous -@admin
The dangerous command categories are defined in Redis ACL:
| Category | Includes | Why it's dangerous |
|---|---|---|
@dangerous | FLUSHALL, FLUSHDB, DEBUG, SHUTDOWN, SCRIPT KILL | Destructive or disruptive |
@admin | CONFIG SET/GET, REPLICAOF, CLUSTER, SLAVEOF | Changes server state |
@slow | KEYS, SORT, SCAN with bad params | Blocks the event loop |
@blocking | BLPOP, BRPOP, BZPOPMIN | Holds connections |
Network isolation¶
The single most effective Redis security measure: don't let untrusted networks talk to Redis at all
# redis.conf - bind to specific interfaces
bind 127.0.0.1 10.0.1.50
# If Redis should only be accessible from localhost (same machine):
bind 127.0.0.1
# iptables - whitelist only application servers
iptables -A INPUT -p tcp --dport 6379 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
# If using Docker: never publish Redis port to host
# docker run -d --name redis --network app_network redis:7
# Docker internal network only - no -p flag
Persistence security¶
Redis offers two persistence mechanisms, both of which write data to disk. If the disk files are accessible to unauthorized users, your cached data is exposed
RDB (Redis Database) - point-in-time snapshots¶
# redis.conf
save 900 1 # Save if at least 1 key changed in 900 seconds
save 300 10 # Save if at least 10 keys changed in 300 seconds
save 60 10000 # Save if at least 10000 keys changed in 60 seconds
# File permissions
dir /var/lib/redis
dbfilename dump.rdb
# Ensure: chmod 600 /var/lib/redis/dump.rdb
# Ensure: chown redis:redis /var/lib/redis/ -R
AOF (Append-Only File) - every write operation logged¶
# redis.conf
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec # fsync every second (good balance)
# appendfsync always # Every write (slowest but safest)
# appendfsync no # Let OS handle it (fastest but least safe)
# AOF rewrite (compacts the log)
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
Encryption for persistence files¶
If the Redis server disk is compromised (stolen backup, cloud snapshot exposed), unencrypted RDB/AOF files leak all cached data:
# Use filesystem-level encryption
# LUKS for block devices, eCryptfs for directories
# Or store Redis data on encrypted cloud volumes (EBS encryption, GCE PD encryption)
# For the data directory:
sudo cryptsetup luksFormat /dev/xvdf
sudo cryptsetup open /dev/xvdf redis-crypt
sudo mkfs.ext4 /dev/mapper/redis-crypt
sudo mount /dev/mapper/redis-crypt /var/lib/redis
Sentinel and cluster security¶
Redis Sentinel and Redis Cluster add additional attack surfaces because they introduce additional communication channels between nodes that can be exploited
# sentinel.conf
sentinel auth-pass mycluster sentinel_shared_secret
# All sentinels must authenticate with the same password
# Require TLS for sentinel-to-sentinel communication
sentinel tls-port 26379
sentinel tls-replication yes
# Cluster communication
# cluster-config-file nodes.conf (contains cluster topology - protect it)
# cluster-require-full-coverage no (continue serving partial data during partition)
For production Redis Cluster deployments, use a service mesh (Istio, Linkerd) or cloud-managed Redis (AWS ElastiCache, Redis Cloud) that handles node-to-node encryption and access control - rolling your own cluster security is complex and easy to misconfigure
prerequisites¶
db_11_redis_patterns.md - you should understand Redis data types and common usage patterns before the security implications of each pattern make sense. Knowing what FLUSHALL does is meaningless if you don't know why losing a cache population hurts
next → db_13_sqlite.md