Redis hardening plan for a cache:-only app
Right now anyone who can reach port 6379 has full control. That includes CONFIG SET dir and SLAVEOF, which attackers commonly use to get code execution or to write SSH keys. Check for compromise before you harden.
Step 0: Check whether it's already compromised
redis-cli CONFIG GET dir; redis-cli CONFIG GET dbfilename
redis-cli CLIENT LIST; redis-cli INFO replication
redis-cli --scan | grep -v '^cache:' | head # unexpected keys
ls -la ~/.ssh/authorized_keys /etc/cron.d /var/spool/cron # unexpected entries
If anything looks wrong, treat the host as breached and rebuild it. Rotate any secrets that were stored in Redis.
Step 1: Firewall first (immediate, no app change)
Allow only the app host's IP. This example uses ufw; use the iptables equivalent if you prefer.
ufw default deny incoming
ufw allow from <APP_SERVER_IP> to any port 6379 proto tcp
ufw allow 22/tcp # ideally restricted to your IP too
ufw enable
If the VPS provider has a cloud firewall or security group, set the same rule there too. Docker bypasses ufw through its own iptables rules, so if Redis runs in Docker, publish the port as 127.0.0.1:6379:6379 or use the DOCKER-USER chain.
Step 2: Create ACL users
Don't use a single requirepass. Disable the default user and give the app a user scoped to cache:*. Generate the passwords with openssl rand -hex 32.
/etc/redis/users.acl:
user default off
user app on #<sha256 of app password> ~cache:* &* -@all +get +set +mget +mset +del +unlink +exists +expire +pexpire +ttl +pttl +incr +decr +scan +ping +hello +auth
user admin on #<sha256 of admin password> ~* &* +@all
&*can be changed toresetchannelsif the app doesn't use pub/sub.- Trim the command list to what the app actually uses. If it needs hashes, add
+hget +hsetand so on. - Hash the passwords with
echo -n 'pw' | sha256sum, so no plaintext is stored in the file. - Keep
adminfor operators only, and prefer reaching it over localhost or SSH. SCANisn't filtered by key pattern, so give the app+scanonly if it needs it. It will see key names, but not values outsidecache:*.
Step 3: redis.conf
# Network
bind 127.0.0.1 <PRIVATE_OR_PUBLIC_IFACE_IP> # not 0.0.0.0
port 0 # disable plaintext if using TLS below
protected-mode yes
# Auth
aclfile /etc/redis/users.acl
# TLS (needed if traffic crosses the public internet)
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 optional # use "yes" for mutual TLS
tls-protocols "TLSv1.2 TLSv1.3"
# Dangerous commands (ACLs already block them for `app`; this is defence in depth)
rename-command DEBUG ""
rename-command SHUTDOWN ""
# Prefer ACLs over renaming CONFIG/FLUSHALL, since rename-command is deprecated and breaks tooling.
# Cache behaviour
maxmemory 1gb
maxmemory-policy allkeys-lru
save "" # drop persistence if it's purely a cache
appendonly no
Also run as an unprivileged redis user. With systemd, add NoNewPrivileges=yes, ProtectSystem=full and ProtectHome=yes. Keep /etc/redis at mode 640, owned by root:redis.
Step 4: Roll out without an outage
- Apply the firewall (Step 1). The app keeps working.
- Add the ACL users while Redis is live, and test them from the app host:
redis-cli --tls --user app --askpass SET cache:x 1 # OK redis-cli --tls --user app --askpass SET other:x 1 # NOPERM redis-cli --tls --user app --askpass FLUSHALL # NOPERM - Deploy the app with the new credentials, and with TLS if it's enabled.
- Restart Redis with the final config. The restart requires a maintenance window, because
bind,tls-portandprotected-modecan't all be changed on a live instance. - Confirm from outside the allowed IP that the port is closed:
nmap -p 6379 <vps_ip>.
Step 5: Ongoing
- Set
slowlogandlatency-monitorand ship the logs somewhere. Alert onNOPERMandWRONGPASSspikes (ACL LOG). - Keep Redis patched, and keep the OS up to date.
- Rotate the app password on a schedule. ACL users allow multiple passwords at once, so rotation needs no downtime.
- If the app and Redis are on the same host, skip the network entirely. Use
bind 127.0.0.1or a unix socket (unixsocket /run/redis/redis.sock,unixsocketperm 770).
Notes
- If the app is on the same private network, TLS is optional but still recommended. Across the public internet it is mandatory.
- I tightened the example ACLs from the reference material. Its
app_writerexample uses~*with+@all -@dangerous, which isn't limited tocache:*.
I can also write the config files out or review your current redis.conf if you'd like.
Pure-instruction skill, so the trial gave the model only the Skill and Read tools: no shell and no Redis server, and none of the commands were run. The answer goes beyond the skill text (for example ACL password hashes and Docker firewall notes); treat those parts as the model's own additions and test every setting on a staging copy first.
它做什么
告诉模型 Redis 官方建议怎样加固生产环境:一定要认证并配合 TLS,每个应用单独用一个 ACL 用户,别让服务器暴露在公网。
工作方式
- 认证与 TLS:
requirepass,更推荐 ACL 用户;tls-port和证书配置,以及 Python、Java 的客户端写法。 - ACL:给出只读缓存用户、不能执行危险命令的写入用户、管理员三类示例,以及
@read、@write、@dangerous、@admin等命令类别。 - 网络:
bind到指定网卡并保持protected-mode yes,用防火墙只放行应用所在网段,必要时禁用破坏性命令。
适合
把 Redis 部署上线前加固、给应用设计 ACL 用户、处理扫描器报出的“Redis 暴露在公网”。
局限
内容很短(约 7 KB),不涉及云厂商的设置、Redis Cluster 和审计工具。
低风险:纯指令文件,来自 Redis 官方仓库(MIT 协议)。没有脚本、不联网、自身不写文件,也不需要账号或密钥。但它的建议会改变生产服务器的暴露方式(监听地址、防火墙规则、ACL、禁用命令)。如果你或你的智能体照着做,配错一条规则可能把你锁在门外或让应用不可用:先在测试环境验证,改防火墙或 ACL 时保持另一个会话不断开,并留好回退办法。