Web Security

Redis Security Configuration: Authentication, TLS, and ACL Setup

Secure Redis with requirepass vs ACL users, TLS mode configuration, bind interface restrictions, rename-command for dangerous commands, and Lua scripting risks.

March 9, 20267 min readShipSafer Team

Redis Security Configuration: Authentication, TLS, and ACL Setup

Redis was designed as a low-latency in-memory cache for internal network use — its original documentation explicitly warned against exposing it to the internet. Yet misconfigured Redis instances remain one of the most common findings in security assessments. Thousands of Redis instances are publicly accessible with no authentication. This guide covers the complete security configuration stack.

The Threat Model

A publicly accessible Redis instance without authentication gives an attacker:

  • Read/write access to all cached data (sessions, tokens, user data)
  • The ability to flush all data (FLUSHALL)
  • Code execution via the Lua scripting engine
  • Historical exploitation: writing SSH keys to /root/.ssh/authorized_keys via CONFIG SET dir and CONFIG SET dbfilename

The fixes are not complex, but they require deliberate configuration.

Step 1: Bind to Specific Interfaces

The first and most important control: do not listen on all interfaces.

# redis.conf

# WRONG — listens on all interfaces including external
# bind 0.0.0.0

# Correct — listen only on loopback and specific private interface
bind 127.0.0.1 10.0.0.5

# If Redis is in a container and only needs loopback
bind 127.0.0.1

Combined with a firewall rule that blocks Redis's port (6379) from the internet, this is your primary network-level defense.

# UFW — block Redis from external access
ufw deny 6379
ufw allow from 10.0.0.0/8 to any port 6379  # Allow internal network only

Step 2: Authentication — requirepass vs ACL Users

Legacy: requirepass (Redis < 6.0)

# redis.conf
requirepass "YourStrongPasswordHere-UseAtLeast32Chars"
# Connect with password
redis-cli -a "YourStrongPasswordHere-UseAtLeast32Chars"

# Or authenticate after connecting
redis-cli
> AUTH YourStrongPasswordHere-UseAtLeast32Chars

requirepass is a single shared password. All clients use the same credential. It has no per-user permissions.

Modern: ACL Users (Redis 6.0+)

ACL (Access Control List) provides per-user authentication with fine-grained command and key permissions:

# redis.conf — disable default user and create named users

# Disable the default user (or give it a strong password with no permissions)
user default off

# Application user — can only access app:* keys, no admin commands
user appuser on >StrongPassword123! ~app:* &* +@read +@write +@string +@hash +@list -@admin -@dangerous

# Read-only analytics user
user analyticsuser on >AnalyticsPass456! ~app:* &* +@read

# Admin user — full access, but use sparingly
user adminuser on >AdminPass789! ~* &* +@all

ACL syntax breakdown:

  • on — user is active
  • >password — set password (prefix with >)
  • ~app:* — can only access keys matching app:*
  • &* — can subscribe to any pub/sub channel
  • +@read — allow all read commands
  • -@admin — deny admin commands like CONFIG, DEBUG, KEYS

View and manage ACLs at runtime:

# List all users
redis-cli ACL LIST

# Create user at runtime
redis-cli ACL SETUSER newuser on >password ~data:* +@read

# Test what a user can do
redis-cli ACL GETUSER appuser

# Load ACL changes from file
redis-cli ACL LOAD

Store ACL rules in a separate file:

# redis.conf
aclfile /etc/redis/users.acl

Step 3: TLS Configuration

For production Redis, use TLS to encrypt data in transit:

# redis.conf — TLS mode
tls-port 6380
port 0  # Disable unencrypted port

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

# Require client certificates (mutual TLS)
tls-auth-clients yes

# Minimum TLS version
tls-protocols "TLSv1.2 TLSv1.3"

# Cipher suites (TLS 1.2)
tls-ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"

Connecting with TLS:

redis-cli --tls \
  --cert /etc/redis/tls/client.crt \
  --key /etc/redis/tls/client.key \
  --cacert /etc/redis/tls/ca.crt \
  -p 6380

In Node.js:

import { createClient } from 'redis';
import { readFileSync } from 'fs';

const client = createClient({
  socket: {
    host: 'redis.internal',
    port: 6380,
    tls: true,
    cert: readFileSync('/etc/redis/tls/client.crt'),
    key: readFileSync('/etc/redis/tls/client.key'),
    ca: readFileSync('/etc/redis/tls/ca.crt'),
  },
  password: 'StrongPassword123!',
});

Step 4: Rename or Disable Dangerous Commands

Redis has commands that can be catastrophic if called by unauthorized users or malicious code. Use rename-command to disable or rename them:

# redis.conf

# Disable completely (rename to empty string)
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command DEBUG ""
rename-command CONFIG ""
rename-command SHUTDOWN ""
rename-command KEYS ""     # Use SCAN instead — KEYS blocks and can cause downtime

# Rename to obscure names (useful if you still need admin access)
rename-command CONFIG "CONFIG_8f2a9b3c"

Note: rename-command is incompatible with ACL-based configurations in Redis 7.0+. In Redis 7.0+, use ACLs to deny these commands to application users instead:

# In users.acl
user appuser on >password ~app:* +@all -@admin -@dangerous -flushall -flushdb -keys -config -debug

Step 5: Protect Against Configuration Abuse

Historically, unprotected Redis instances were exploited by changing dir and dbfilename to write files anywhere on the filesystem:

# Classic Redis exploitation — write SSH key
redis-cli CONFIG SET dir /root/.ssh/
redis-cli CONFIG SET dbfilename authorized_keys
redis-cli SET payload "ssh-rsa AAAA..."
redis-cli BGSAVE

Defenses:

  1. Disable or rename CONFIG command (above)
  2. Run Redis as a dedicated low-privilege user (not root)
  3. Use ACLs to deny CONFIG to application users
# systemd — run Redis as redis user, not root
User=redis
Group=redis

Step 6: Lua Scripting Security

Redis's Lua scripting engine (EVAL, EVALSHA) executes arbitrary Lua code on the server. This is intentional but dangerous:

# Disable Lua completely if not needed
rename-command EVAL ""
rename-command EVALSHA ""

# Or restrict to admin users via ACL
user appuser on >password ~* -eval -evalsha +@all

If you use Lua scripts legitimately, load them as named scripts (SCRIPT LOAD) and call them by SHA, rather than sending raw Lua code dynamically.

Step 7: Protected Mode

Redis 3.2+ includes protected mode, which blocks connections from non-loopback addresses if no authentication is configured. Keep it enabled:

protected-mode yes

This is a safety net, not a primary control. Always configure authentication and bind to specific interfaces regardless.

Step 8: Disable Persistence If Not Needed

If Redis is used purely as a cache (not as a primary data store), disable persistence to remove the risk of data being written to disk:

# redis.conf — disable RDB snapshots
save ""

# Disable AOF
appendonly no

Without persistence, there is no RDB file to steal even if an attacker gains server access.

Complete Hardened redis.conf Example

# Network
bind 127.0.0.1 10.0.0.5
protected-mode yes
port 0
tls-port 6380

# 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-auth-clients yes
tls-protocols "TLSv1.2 TLSv1.3"

# Auth (Redis 6+)
aclfile /etc/redis/users.acl

# Dangerous command restrictions
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command DEBUG ""

# Disable Lua if not needed
rename-command EVAL ""

# Logging
loglevel notice
logfile /var/log/redis/redis-server.log

# No persistence for cache-only deployments
save ""
appendonly no

Security Checklist

  • bind set to specific interfaces — not 0.0.0.0
  • Firewall rules block port 6379 from the internet
  • ACL users configured with least-privilege command/key access
  • Default user disabled or restricted
  • TLS enabled for all connections in production
  • FLUSHALL, FLUSHDB, DEBUG, KEYS renamed or disabled
  • CONFIG access restricted to admin ACL users
  • Redis runs as dedicated low-privilege OS user
  • protected-mode yes enabled
  • Lua scripting disabled if not required

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.