Context: Why Is Redis Frequently Targeted by Attackers?
In production environments, Redis handles tens of thousands of requests per second thanks to its in-memory architecture. This speed is achieved because Redis prioritizes maximum performance and sheds most heavy security overhead. The original design philosophy of Redis assumed instances would always run inside an isolated, fully trusted internal network.
Day-to-day operations tell a different story. Shodan statistics consistently uncover more than 30,000 Redis servers exposing port 6379 directly to the public Internet without any password protection. With just a few seconds of port scanning, an attacker can connect directly to your instance.
The damage goes far beyond leaking user sessions or API tokens. A prime example is the Kinsing cryptojacking campaign: attackers exploit Redis write permissions, executing commands like CONFIG SET dir /var/spool/cron/crontabs or /root/.ssh to inject malicious payloads, plant a shell, and gain root access to the Linux host. Securing Redis from the very moment a server is provisioned is therefore an absolute necessity.
Environment Setup
This guide is demonstrated on Ubuntu 22.04 LTS. The configuration is virtually identical for Debian 11/12 or Rocky Linux/RHEL 9. To take full advantage of ACLs and native TLS, your system requires Redis 6.0 or higher.
Install Redis Server alongside the OpenSSL package to generate certificates:
sudo apt update
sudo apt install redis-server openssl -y
# Verify version (requires >= 6.0)
redis-server -v
Verify that the systemd service is running properly:
sudo systemctl status redis-server
Step-by-Step Redis Security Configuration
1. Restrict Network Interfaces and Enable Protected Mode
Most Redis security incidents stem from carelessly binding to 0.0.0.0. Ensure you explicitly bind only to the loopback address or a private server IP within your VPC subnet (such as 10.0.1.5).
Open the configuration file:
sudo nano /etc/redis/redis.conf
Locate and update the following two directives:
bind 127.0.0.1 ::1
protected-mode yes
If your backend application resides on the same host as Redis, the configuration above is sufficient. When protected-mode yes is enabled, Redis automatically rejects all external connections if no authentication password has been configured.
2. Disable or Rename Dangerous Commands
Certain administrative commands in Redis carry extreme risk. Running FLUSHALL can instantly wipe millions of cached keys in a split second. The CONFIG command suite allows runtime configuration overrides and arbitrary system file manipulation.
Add the following directives to /etc/redis/redis.conf:
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command CONFIG "SYS_ADMIN_CONFIG_8f9a2b"
Passing an empty string "" completely disables that command. Renaming CONFIG to a randomized string ensures only sysadmins who know the exact string can query or modify runtime settings.
3. Fine-Grained Application Permissions Using ACLs (Access Control Lists)
Prior to Redis 6.0, the requirepass setting applied a single shared password across all clients. Every service—from web apps to background workers and cron jobs—shared the exact same administrative privileges.
Redis ACLs solve this problem fundamentally. Each application can have its own dedicated user account, restricted to reading and writing only within its assigned key prefix.
Create a dedicated ACL management file:
sudo touch /etc/redis/users.acl
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 600 /etc/redis/users.acl
Declare this file in /etc/redis/redis.conf:
aclfile /etc/redis/users.acl
Open /etc/redis/users.acl to define your users:
sudo nano /etc/redis/users.acl
Sample configuration:
# Disable default user without password
user default off
# User for Web App: access restricted to app:cache: prefix, dangerous commands blocked
user web_app on >K9#mX2$pL9vQ!wZ ~app:cache:* +@read +@write -@dangerous
# Administrator user: full administrative access
user sysadmin on >T7@vR5*bN1#cE8! ~* +@all
ACL syntax breakdown:
user default off: Disables the default account.>Password: Sets a clear-text password (Redis automatically hashes it with SHA-256 in memory).~app:cache:*: Restricts the key namespace. The web service can only interact with keys bearing this prefix, preventing it from snooping on session or billing data belonging to other services.+@read +@write -@dangerous: Grants standard read/write command groups while stripping out commands capable of hanging the server or altering configurations.
4. Encrypt Inter-Server Traffic with TLS
By default, the Redis wire protocol transmits data in plain text. If your backend and Redis live on separate servers across an internal network, an attacker compromising a switch or leveraging ARP spoofing can sniff session tokens flying over the wire.
Enabling TLS introduces roughly 5% to 12% CPU overhead and adds 0.1ms to 0.3ms of latency. In exchange, all payload traffic traversing the network is fully protected.
Generate the key pair and digital certificates (internal self-signed CA):
sudo mkdir -p /etc/redis/tls
cd /etc/redis/tls
# Generate internal CA
sudo openssl genrsa -out ca.key 4096
sudo openssl req -x509 -new -nodes -sha256 -key ca.key -days 3650 -subj '/CN=Internal-Redis-CA' -out ca.crt
# Generate private key and certificate for Redis server
sudo openssl genrsa -out redis.key 2048
sudo openssl req -new -sha256 -key redis.key -subj '/CN=redis-server' -out redis.csr
sudo openssl x509 -req -in redis.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out redis.crt -days 365
# Secure private key file permissions
sudo chown -R redis:redis /etc/redis/tls
sudo chmod 600 /etc/redis/tls/*.key
sudo chmod 644 /etc/redis/tls/*.crt
Update /etc/redis/redis.conf:
# Disable plaintext port
port 0
# Enable TLS encrypted port
tls-port 6379
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 no
Restart the service to apply the full configuration:
sudo systemctl restart redis-server
Testing and Security Auditing
1. Verify ACL Permissions Using redis-cli
Connect over TLS using the newly created web_app user:
redis-cli --tls --cacert /etc/redis/tls/ca.crt -a 'K9#mX2$pL9vQ!wZ' --user web_app
Run test operations to verify authorization rules:
# 1. Operation within allowed prefix -> Success
SET app:cache:session_user_99 "authenticated"
GET app:cache:session_user_99
# 2. Operation outside allowed prefix -> Denied immediately
SET config:jwt_secret "my-secret-key"
# Output: (error) NOPERM this user has no permissions to access the 'config:jwt_secret' key
# 3. Executing blacklisted command -> Blocked
KEYS *
# Output: (error) NOPERM this user has no permissions to run the 'keys' command
2. Monitor Real-Time Security Violations
Redis provides a powerful runtime auditing tool with ACL LOG. Whenever a client submits an invalid password, invokes a forbidden command, or violates a key pattern, Redis records the timestamp, client IP, and offending command:
127.0.0.1:6379> ACL LOG 5
If your logs repeatedly show auth-error or key-perm errors originating from an unexpected IP address, your system is likely undergoing network reconnaissance or an application worker is misconfigured.
Additionally, monitor the service log file to catch certificate loading issues or connection resets:
sudo tail -f /var/log/redis/redis-server.log
Combining these three defense layers—network isolation (bind/port), least-privilege access control (ACLs), and traffic encryption (TLS)—ensures your Redis instance stays resilient against external attacks as well as internal data leakage risks.

