Danh sách bài viết

Bài 113: AUTH Password — requirepass & masterauth

Redis không có authentication mặc định trong các phiên bản cũ — bất kỳ client nào kết nối được đến port 6379 đều có thể đọc/ghi toàn bộ data. requirepass là lớp xác thực đơn giản nhất: một shared password, client phải gửi AUTH trước khi chạy lệnh. Bài này đi sâu vào cơ chế hoạt động, password generation, rotation không downtime, masterauth cho replication, Sentinel và Cluster auth, brute force protection, secrets management và các anti-pattern cần tránh. Đây là nền tảng trước khi chuyển sang ACL (bài 114) cho phân quyền chi tiết hơn.

01/06/2026
0 lượt xem
1

Mục Tiêu Bài Học

  • Hiểu requirepass hoạt động như thế nào và giới hạn của nó.
  • Cấu hình đúng masterauth trên replica — lỗi hay gặp nhất khi setup replication.
  • Tạo password đủ mạnh với openssl rand.
  • Rotate password không cần downtime.
  • Hiểu Sentinel auth và Cluster auth cần cấu hình thêm gì.
  • Lưu trữ password an toàn: tránh hardcode, dùng secret manager.
  • Protect brute force bằng fail2ban.
2

requirepass — Cơ Chế Hoạt Động

requirepass đặt một shared password cho toàn bộ Redis instance. Khi được set, Redis từ chối mọi lệnh từ client chưa xác thực — trừ AUTH, HELLOQUIT.

# redis.conf
requirepass MyStrongP@ssw0rd!

Client phải gửi AUTH password ngay sau khi kết nối và trước bất kỳ lệnh nào khác. Nếu không, Redis trả về:

NOAUTH Authentication required.

Đặc điểm của requirepass:

  • Một password duy nhất cho toàn instance — không phân biệt user, không phân quyền.
  • Password đúng thì có full access: đọc, ghi, xóa, CONFIG, FLUSHALL.
  • Là cơ chế mặc định từ Redis 1.x đến Redis 5.x.
  • Redis 6+ vẫn hỗ trợ nhưng requirepass thực chất được map sang ACL user default.

Cũng có thể set runtime mà không cần restart:

CONFIG SET requirepass "MyStrongP@ssw0rd!"

Lệnh này có hiệu lực ngay lập tức. Các connection hiện tại đã authenticated vẫn hoạt động. Connection mới phải AUTH với password mới.

3

Client AUTH: Python, Node.js, CLI

redis-py (Python):

import redis

# Cách phổ biến: truyền password khi khởi tạo connection
r = redis.Redis(host="127.0.0.1", port=6379, password="MyStrongP@ssw0rd!")
r.ping()  # True nếu auth thành công

# Hoặc explicit AUTH (ít dùng):
r2 = redis.Redis(host="127.0.0.1", port=6379)
r2.execute_command("AUTH", "MyStrongP@ssw0rd!")
r2.ping()

redis-py tự động gửi AUTH sau khi mở connection khi password được cung cấp. Connection pool cũng làm điều này cho mỗi connection mới trong pool.

ioredis (Node.js / TypeScript):

import Redis from "ioredis";

const redis = new Redis({
  host: "127.0.0.1",
  port: 6379,
  password: "MyStrongP@ssw0rd!",
});

await redis.ping(); // "PONG"

redis-cli:

# Option 1: flag -a
redis-cli -h 127.0.0.1 -p 6379 -a "MyStrongP@ssw0rd!"

# Option 2: lệnh AUTH trong session
redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> AUTH MyStrongP@ssw0rd!
OK
127.0.0.1:6379> PING
PONG

Dùng flag -a trong shell script sẽ khiến password hiện trong ps aux — tránh trong production, nên dùng biến môi trường kết hợp REDISCLI_AUTH:

export REDISCLI_AUTH="MyStrongP@ssw0rd!"
redis-cli -h 127.0.0.1 PING
4

AUTH Command (Redis 6+ với ACL)

Redis 6.0 mở rộng cú pháp AUTH để hỗ trợ username:

AUTH password                 -- Redis <= 5 (và default user trên Redis 6+)
AUTH username password        -- Redis 6+ với ACL users

Khi chỉ dùng requirepass (không cấu hình ACL user cụ thể), AUTH password đăng nhập vào default user — backward compatible hoàn toàn.

Redis trả về:

  • OK — auth thành công.
  • WRONGPASS invalid username-password pair or user is disabled. — sai password hoặc user không tồn tại.
  • ERR Client sent AUTH, but no password is set. — Redis không có requirepass và không có ACL user nào cần password.
5

Password Strength & Generation

Redis không có rate limit tích hợp cho AUTH. Trên mạng local (loopback hoặc LAN), Redis có thể xử lý hàng trăm nghìn AUTH requests/giây. Điều này có nghĩa là password ngắn hoặc yếu không đủ bảo vệ nếu attacker có network access.

Ước lượng thời gian brute force (offline, hardware thông thường):

  • 8 ký tự chữ-số: < 1 giờ với 100k req/s và dictionary attack.
  • 16 ký tự ngẫu nhiên: tính năm với brute force thuần.
  • 32 ký tự ngẫu nhiên (base64): không khả thi trong thực tế.

Redis documentation khuyến nghị dùng password dài đủ để làm brute force không khả thi về mặt thời gian ngay cả khi attacker có thể thử nhiều AUTH/s. Mức tối thiểu thực tế là 32 ký tự ngẫu nhiên.

Generate password với openssl:

# 32 bytes = 256-bit entropy, encode base64 (~44 ký tự)
openssl rand -base64 32
# Ví dụ output: K9mXvR2+pLqN8sT3wYuJhBcFdGeIkMoP...

# Nếu muốn chỉ hex (dễ paste hơn):
openssl rand -hex 32
# Ví dụ: a3f8c1e2b4d5...

Password sinh ra nên được lưu ngay vào secret manager — không paste vào terminal history hay file không được bảo vệ.

6

Password Rotation Không Downtime

Thay đổi password trên production cần thực hiện theo thứ tự đúng để tránh disconnect các client đang hoạt động.

Quy trình rotation chuẩn:

  1. Set password mới runtime (không disconnect client hiện tại):
    CONFIG SET requirepass "NewPassword2026!"
    Redis chấp nhận password mới ngay lập tức. Các connection đã authenticated không bị ngắt — chúng tiếp tục dùng session hiện tại.
  2. Persist vào config file:
    CONFIG REWRITE
    Lệnh này ghi requirepass mới vào redis.conf. Nếu không làm bước này, sau khi restart Redis sẽ quay lại password cũ trong file.
  3. Cập nhật tất cả client: Deploy lại application với password mới. Khi connection cũ đóng và mở lại, client dùng password mới để AUTH.
  4. Verify: Dùng password cũ — phải nhận WRONGPASS. Dùng password mới — phải nhận OK.

Lưu ý quan trọng:

  • Các connection đang open không bị kick — chúng vẫn chạy với session đã authenticated. Chỉ khi reconnect mới cần password mới.
  • Nếu client dùng connection pool và pool không reconnect, client sẽ vẫn hoạt động với connection cũ cho đến khi connection bị đóng (timeout, restart app, v.v.).
  • Với replication: update masterauth trên replica trước hoặc đồng thời với đổi requirepass trên master. Nếu đổi master trước, replica mất kết nối đến master.
7

masterauth — Replica Auth Tới Master

Khi master có requirepass, replica cần biết password để kết nối và đồng bộ dữ liệu. masterauth là config trên replica cho mục đích này.

# redis.conf trên replica
replicaof master.host 6379
masterauth MasterPassword

Quá trình xảy ra khi replica kết nối master:

  1. Replica mở TCP connection tới master.
  2. Gửi AUTH MasterPassword.
  3. Nếu OK, gửi REPLCONF và bắt đầu sync.
  4. Nếu WRONGPASS: replication fail, Redis log MASTER aborted replication with an error: WRONGPASS.

masterauth không phải requirepass của replica: Đây là hai config riêng biệt.

  • requirepass trên replica: password để client bên ngoài kết nối đến replica.
  • masterauth trên replica: password để replica tự nó kết nối lên master.

Trong hầu hết setup, replica và master dùng cùng password nên cả hai config được đặt cùng giá trị:

# redis.conf trên replica
requirepass SharedPassword      # client connect tới replica
masterauth SharedPassword       # replica connect tới master

Set runtime:

CONFIG SET masterauth "SharedPassword"

Thiếu masterauth là lỗi hay gặp nhất khi thêm replica vào hệ thống đã có requirepass. Redis log không luôn luôn rõ ràng — có thể chỉ thấy replica không sync mà không có error message rõ ràng ở phía client.

8

Sentinel Auth

Sentinel quản lý master và replica — nó cần authenticate với cả hai. Khi Redis nodes có password, cần cấu hình thêm trong sentinel.conf:

# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster MasterPassword

sentinel auth-pass dùng cho cả master và replica có cùng password. Đây là yêu cầu của Sentinel — master và replica trong cùng một monitored group phải dùng chung password.

Redis 6+ với ACL: Sentinel cũng hỗ trợ chỉ định user:

sentinel auth-user mymaster sentinel-user
sentinel auth-pass mymaster SentinelUserPassword

Client kết nối qua Sentinel thường cần cả password để nói chuyện với Sentinel (nếu Sentinel có requirepass) và password để nói chuyện với Redis node. Đây là hai layer riêng biệt — library như redis-py và ioredis có config riêng cho từng layer.

# redis-py với Sentinel
from redis.sentinel import Sentinel

sentinel = Sentinel(
    [("sentinel1.host", 26379), ("sentinel2.host", 26379)],
    sentinel_kwargs={"password": "SentinelPassword"},  # auth tới Sentinel
    password="MasterPassword",                          # auth tới Redis node
)
master = sentinel.master_for("mymaster")
master.ping()
9

Cluster Auth

Trong Redis Cluster, các node giao tiếp với nhau qua cluster bus (port = data port + 10000). Bus này cũng cần authentication khi requirepass được đặt.

Mỗi node trong cluster cần cả hai config:

# redis.conf trên mỗi node trong cluster
requirepass ClusterPassword     # client kết nối tới node này
masterauth ClusterPassword      # node này kết nối tới master (khi là replica)

Tất cả nodes trong cluster phải dùng cùng password. Khác password giữa các node sẽ làm cluster bus authentication fail và node bị cô lập khỏi cluster.

Client kết nối cluster mode cần password giống như kết nối standalone:

import redis

r = redis.RedisCluster(
    startup_nodes=[{"host": "node1", "port": 6379}],
    password="ClusterPassword",
)
r.ping()
10

Brute Force Protection

Redis không có cơ chế lockout tích hợp sau N lần AUTH fail. Không có delay, không có IP ban, không có exponential backoff. Đây là trách nhiệm của infrastructure layer bên ngoài.

fail2ban: Cách phổ biến nhất để block IP sau nhiều lần fail.

# /etc/fail2ban/filter.d/redis-auth.conf
[Definition]
failregex = .*WRONGPASS.* from <HOST>:.*
ignoreregex =
# /etc/fail2ban/jail.d/redis.conf
[redis]
enabled = true
port    = 6379
filter  = redis-auth
logpath = /var/log/redis/redis-server.log
maxretry = 5
findtime = 300
bantime  = 3600

Cấu hình trên block IP sau 5 lần WRONGPASS trong 5 phút, ban 1 giờ.

Yêu cầu Redis phải log AUTH errors: Mặc định Redis log level là notice — WRONGPASS events được log. Verify:

CONFIG GET loglevel
# Cần: "notice" hoặc "verbose"

iptables / nftables: Nếu không muốn dùng fail2ban, giới hạn connection rate tới port 6379:

# Chỉ cho phép 10 connection mới/giây từ mỗi IP
iptables -A INPUT -p tcp --dport 6379 -m state --state NEW \
  -m recent --set --name redis_conn
iptables -A INPUT -p tcp --dport 6379 -m state --state NEW \
  -m recent --update --seconds 1 --hitcount 11 --name redis_conn -j DROP

Cả hai cách trên đều là lớp bổ sung — không thay thế password mạnh và network isolation (đã đề cập trong bài trước).

11

Password Trong Config & Secrets Management

Vấn đề cơ bản: Redis config file lưu password dạng plaintext. Nếu file này bị đọc (leak, misconfigured permission, log backup ra ngoài), password bị lộ.

# KHÔNG làm: pass password qua command line argument
redis-server --requirepass MyPassword
# 'ps aux' hiển thị:
# redis-server --requirepass MyPassword  <-- password visible
# Tốt hơn: dùng config file
redis-server /etc/redis/redis.conf
# redis.conf có: requirepass MyPassword
# Bảo vệ file: chmod 600 /etc/redis/redis.conf

Tốt nhất là không lưu password cố định trong file config mà load từ secret manager lúc startup.

HashiCorp Vault:

#!/bin/bash
# startup script
REDIS_PASS=$(vault kv get -field=password secret/redis/prod)
redis-server /etc/redis/redis.conf --requirepass "$REDIS_PASS"

AWS Secrets Manager:

REDIS_PASS=$(aws secretsmanager get-secret-value \
  --secret-id redis-prod \
  --query SecretString \
  --output text | jq -r .password)

Kubernetes Secret:

apiVersion: v1
kind: Secret
metadata:
  name: redis-secret
type: Opaque
stringData:
  password: "MyStrongP@ssw0rd!"
---
# Trong Redis Pod/Deployment
env:
  - name: REDIS_PASSWORD
    valueFrom:
      secretKeyRef:
        name: redis-secret
        key: password

Sau đó trong entrypoint script:

redis-server /etc/redis/redis.conf --requirepass "$REDIS_PASSWORD"

Application code:

import os
import redis

# Không làm: hardcode
r = redis.Redis(password="hardcoded_password")

# Đúng: từ environment
r = redis.Redis(password=os.environ["REDIS_PASSWORD"])

# Tốt hơn: từ secret store (ví dụ với AWS SDK)
import boto3, json
sm = boto3.client("secretsmanager", region_name="ap-southeast-1")
secret = json.loads(sm.get_secret_value(SecretId="redis-prod")["SecretString"])
r = redis.Redis(password=secret["password"])

Không commit Docker Compose với password plaintext:

# docker-compose.yml — KHÔNG commit lên git
services:
  redis:
    image: redis:7
    command: redis-server --requirepass "${REDIS_PASSWORD}"
    # Dùng .env file (gitignored) cho REDIS_PASSWORD
12

AUTH Logging & Audit

Một lo ngại khi bật logging chi tiết là password bị leak trong log. Cụ thể:

  • MONITOR: Lệnh MONITOR dump tất cả commands đang chạy — bao gồm cả AUTH password. Trên Redis 6.x trở về trước, password xuất hiện plaintext trong output của MONITOR.
  • SLOWLOG: Nếu AUTH command chậm (hiếm, nhưng có thể khi Redis quá tải), nó xuất hiện trong slowlog kèm argument — có thể bao gồm password.

Redis 7.0+ obfuscation: Redis 7.0 thêm tính năng obfuscate các sensitive arguments trong logging. AUTH password bị che dấu trong MONITOR output và SLOWLOG khi Redis phát hiện đó là sensitive command. Verify:

# Trên Redis 7.0+
MONITOR
# Bạn sẽ thấy: "AUTH" "(redacted)" thay vì password plaintext

Nếu đang dùng Redis < 7.0 trong production, tránh bật MONITOR trên hệ thống live và limit ai có quyền chạy MONITOR.

Audit AUTH events:

  • Log thành công/thất bại AUTH theo source IP.
  • Alert khi WRONGPASS từ một IP vượt ngưỡng (potential brute force).
  • Alert khi AUTH từ IP lạ thành công (unexpected access).

Redis 7.2 có ACL log (ACL LOG) chi tiết hơn — nhưng chủ đề này sẽ đề cập trong bài ACL (bài 114).

13

requirepass Và ACL Default User

Từ Redis 6.0, requirepass X là syntactic sugar cho:

ACL SETUSER default on >X ~* &* +@all

Tức là: user default được bật (on), password là X, được phép truy cập tất cả keys (~*), tất cả channels (&*), tất cả commands (+@all).

Điều này có nghĩa là nếu bạn dùng cả requirepass và ACL, chúng có thể conflict. Thứ tự ưu tiên: ACL rule ghi đè requirepass. Nếu dùng ACL, nên dùng ACL hoàn toàn và không set requirepass.

Disable default user (khi chuyển sang ACL):

# Tạo user admin riêng trước
ACL SETUSER admin on >adminpass ~* &* +@all

# Sau đó disable default user
ACL SETUSER default off

Sau đó client phải dùng AUTH admin adminpass thay vì AUTH adminpass. Bài 114 sẽ đi sâu vào toàn bộ ACL system.

14

Anti-patterns & Best Practices

Anti-patterns:

Anti-pattern Hậu quả
Không đặt AUTH (Redis ≤ 5 default) Ai connect được port đều có full access
Password ngắn (< 16 ký tự) Có thể bị brute force nếu network access mở
Hardcode password trong source code Leak qua git history, log, crash dump
Password trong Docker Compose commit lên git Ai clone repo đều thấy password
Quên masterauth trên replica Replication fail ngay khi master có requirepass
Master và replica khác password Replication fail với WRONGPASS, không sync được
Pass password qua --requirepass CLI arg Password visible trong ps aux
Không bao giờ rotate password Nếu bị leak, attacker có access vô hạn thời gian
Không có brute force protection Redis nhận AUTH không giới hạn, dễ bị scan
Không migrate sang ACL khi đã dùng Redis 6+ Không có phân quyền, một password = full access

Best practices:

  • Password tối thiểu 32 ký tự ngẫu nhiên — dùng openssl rand -base64 32.
  • Lưu password trong secret manager (Vault, AWS Secrets Manager, K8s Secret).
  • Rotate mỗi 3–6 tháng hoặc ngay khi nghi ngờ bị leak.
  • Đặt masterauth trên mọi replica và Sentinel ngay từ đầu.
  • Dùng fail2ban để block IP sau nhiều lần AUTH fail.
  • Audit WRONGPASS events — alert khi có spike.
  • Không dùng flag -a trong redis-cli script; dùng REDISCLI_AUTH env var.
  • Khi chạy Redis 6+, lên kế hoạch migrate sang ACL cho phân quyền chi tiết hơn.
  • Có runbook document quy trình rotation và password recovery.
15

Quiz

  1. Redis có requirepass MyPass. Bạn thêm một replica mới nhưng replication không sync. Redis log cho thấy lỗi WRONGPASS. Replica cần config gì?
  2. Bạn đổi password trên master bằng CONFIG SET requirepass NewPass. Các connection từ application đang mở có bị ngắt ngay không? Khi nào application cần dùng password mới?
  3. Vì sao truyền password qua redis-server --requirepass MyPass trên production là không an toàn? Thay thế là gì?
  4. Trong Redis Cluster 3 shard, bạn đặt password khác nhau trên mỗi shard. Hậu quả là gì?
  5. Lệnh MONITOR trên Redis 6.2 (không phải 7.0+) có thể leak password như thế nào?

Đáp án gợi ý

  1. Replica thiếu masterauth MyPass. Thêm vào redis.conf của replica hoặc chạy CONFIG SET masterauth MyPass. Replica cần authenticate với master trước khi bắt đầu sync.
  2. Không — connection đang open không bị kick. Redis chỉ yêu cầu AUTH với password mới khi client tạo connection mới. Application cần password mới khi reconnect: sau khi restart app, sau khi connection pool timeout đóng connection cũ, hoặc khi network giữa client và Redis bị cắt.
  3. ps aux hoặc /proc/[pid]/cmdline hiển thị toàn bộ command line bao gồm password. Bất kỳ user nào có quyền đọc process info đều thấy. Thay thế: lưu password trong file config với chmod 600, hoặc pass qua environment variable và đọc trong startup script.
  4. Cluster inter-node bus sẽ fail authentication khi node này kết nối node khác. Nodes bị isolated, cluster không hoạt động đúng — có thể split-brain. Tất cả nodes trong cluster phải dùng cùng password.
  5. MONITOR dump tất cả commands gửi tới Redis kèm arguments dạng plaintext. Lệnh AUTH password sẽ xuất hiện trong output với password thật. Trên Redis < 7.0 không có obfuscation. Ai có quyền chạy MONITOR trên instance production có thể capture password.

Bài tiếp theo

Bài 114 đi vào Redis ACL (Redis 6+): tạo user riêng biệt, gán permission theo command category, giới hạn key pattern, và thay thế requirepass bằng granular access control.

Tham khảo