Cài đặt và cấu hình Redis trên Fedora Server: Xử lý SELinux và firewalld để triển khai cache server hiệu năng cao

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

2 giờ sáng. App production liên tục trả về lỗi connection timeout. Mình mở log ra thì thấy Redis client không kết nối được. Mình vừa xong việc cài Redis trên Fedora Server mới setup buổi chiều — test local thì redis-cli ping ra PONG ngon lành — nhưng app từ server khác thì timeout hoàn toàn.

Đây là bài học đầu tiên mình học được khi làm việc với Fedora: nó không phải Ubuntu. SELinux enforcing và firewalld cứng hơn nhiều, và nếu không xử lý cả ba lớp — bind address, firewall, SELinux — thì ngồi debug đến sáng cũng không ra.

Vấn đề thực tế gặp phải

Cài Redis xong, start service, test ngay trên server thì ổn. Nhưng app Node.js chạy trên server khác trong cùng mạng nội bộ connect vào thì timeout sau đúng 30 giây.

Check /var/log/redis/redis.log — không có gì bất thường. Check systemctl status redis — running. Nghi firewall, check firewall-cmd --list-ports — không có port 6379. Mở port, reload, test lại — vẫn timeout.

Đến đây mình mới nhớ: Fedora enforcing SELinux từ mặc định. Ubuntu thường dùng AppArmor với profile lỏng hơn nhiều. Fedora thì SELinux strict from day one, không ai nói trước cho mình cả.

Phân tích nguyên nhân

Ngồi trace lại thì có ba thứ phải xử lý đồng thời — debug từng cái một là nguyên nhân mất cả tiếng:

  • Redis bind address: Mặc định Redis chỉ lắng nghe 127.0.0.1 — chỉ local access, app từ server khác không tài nào kết nối được
  • firewalld: Port 6379 mặc định bị block hoàn toàn, không exception
  • SELinux: Ngay cả khi đã mở firewall, SELinux vẫn có thể chặn Redis bind port hoặc block network connection từ process khác

Ba cái này phải xử lý cả ba. Bỏ sót một là ngồi debug tiếp.

Cài đặt Redis trên Fedora Server

Bước 1: Cài Redis từ repo mặc định

Mình dùng Fedora làm máy development chính đã 2 năm — Redis trên repo Fedora thường khá mới, hiện tại là 7.x, không cần thêm repo bên ngoài. Package policycoreutils-python-utils cài kèm để có audit2allowaudit2why dùng ở bước SELinux sau.

sudo dnf install redis policycoreutils-python-utils -y

# Kiểm tra version
redis-server --version

Bước 2: Cấu hình Redis

File cấu hình chính tại /etc/redis/redis.conf. Backup trước khi sửa:

sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sudo nano /etc/redis/redis.conf

Các dòng cần thay đổi:

# Bind cả localhost và IP nội bộ của server
# Thay 192.168.1.100 bằng IP thực của interface mạng nội bộ
bind 127.0.0.1 192.168.1.100

# Đặt password — bắt buộc nếu expose ra network
# Redis 6+ hỗ trợ ACL mạnh hơn, nhưng requirepass đủ cho setup đơn giản
requirepass YourStrongPassword123!

# Giới hạn memory — rule of thumb: ~25-30% tổng RAM server
# 512mb phù hợp cho server 2-4GB RAM
maxmemory 512mb
maxmemory-policy allkeys-lru

# Port mặc định
port 6379

Về bind address: Nếu app và Redis cùng server, giữ 127.0.0.1. Nếu cần kết nối từ server khác, thêm IP interface nội bộ. Tránh dùng 0.0.0.0 trên production trừ khi firewall đã chặt chẽ.

Bước 3: Enable và start service

sudo systemctl enable redis --now
sudo systemctl status redis

Giải quyết vấn đề SELinux

Phần này hay bị skip nhất — hầu hết tutorial Redis viết cho Ubuntu, không đả động đến SELinux. Trên Fedora thì khác: enforcing mode từ ngày đầu, và không nên tắt bằng setenforce 0. Cách đúng là tạo policy.

Kiểm tra SELinux có đang block không

# Xem denial gần đây liên quan Redis
sudo ausearch -m avc -ts recent | grep redis

# Xem thông báo setroubleshoot
sudo journalctl -t setroubleshoot | tail -50

Nếu thấy dòng kiểu avc: denied \{ name_connect \} liên quan Redis — đúng rồi, SELinux đang block.

Cách 1: Bật boolean SELinux có sẵn

# Xem toàn bộ boolean liên quan Redis
sudo getsebool -a | grep redis

# Cho phép các kết nối mạng cần thiết
sudo setsebool -P redis_can_network_connect on

Tên boolean phụ thuộc vào Fedora version — nếu redis_can_network_connect không có trong danh sách, skip thẳng xuống Cách 2.

Cách 2: Tạo SELinux policy từ audit log (chính xác nhất)

Cách này mình hay dùng hơn — tạo policy từ chính những gì bị block thực tế, không guess:

# Xem lý do bị block
sudo ausearch -m avc -ts recent | grep redis | audit2why

# Tạo policy module
sudo ausearch -m avc -ts recent | grep redis | audit2allow -M redis_custom

# Apply policy
sudo semodule -i redis_custom.pp

# Kiểm tra module đã load
sudo semodule -l | grep redis

Nếu đổi thư mục data của Redis

Khi thay đổi data dir khỏi mặc định /var/lib/redis, phải gán lại SELinux context:

# Ví dụ đổi sang /data/redis
sudo semanage fcontext -a -t redis_db_t "/data/redis(/.*)?" 
sudo restorecon -Rv /data/redis

Cấu hình firewalld

Mở port — nhưng đúng cách

Mở toàn bộ port 6379 cho mọi IP là cách nhanh nhưng không an toàn. Dùng rich rule để chỉ cho phép subnet nội bộ:

# Chỉ cho phép subnet 192.168.1.0/24 kết nối Redis
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="6379" protocol="tcp" accept'
sudo firewall-cmd --reload

# Kiểm tra rules đã apply
sudo firewall-cmd --list-rich-rules

Nếu chỉ có một app server cụ thể cần kết nối:

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.50" port port="6379" protocol="tcp" accept'
sudo firewall-cmd --reload

Dùng zone internal thay vì rich rules

Có interface mạng nội bộ riêng (ví dụ eth1)? Zone internal sạch hơn và dễ quản lý về sau:

# Thêm interface nội bộ vào zone internal
sudo firewall-cmd --permanent --zone=internal --add-interface=eth1

# Mở Redis port trong zone internal
sudo firewall-cmd --permanent --zone=internal --add-port=6379/tcp
sudo firewall-cmd --reload

Checklist triển khai Redis bảo mật trên Fedora

Sau vài lần gặp sự cố 2 giờ sáng, đây là quy trình mình đang chạy cho production — theo thứ tự này:

# 1. Cài đặt
sudo dnf install redis policycoreutils-python-utils -y

# 2. Cấu hình Redis với password và bind address
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
# Sửa bind, requirepass, maxmemory trong /etc/redis/redis.conf

# 3. Start service
sudo systemctl enable redis --now

# 4. Chạy thử ~5 phút để SELinux tạo audit events, rồi tạo policy
sudo ausearch -m avc -ts recent | grep redis | audit2allow -M redis_custom
sudo semodule -i redis_custom.pp

# 5. Mở firewall cho subnet nội bộ
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="6379" protocol="tcp" accept'
sudo firewall-cmd --reload

# 6. Test từ máy khác trong mạng
redis-cli -h 192.168.1.100 -p 6379 -a YourStrongPassword123! ping

Kiểm tra sau khi setup

# Xác nhận Redis đang listen đúng interface
sudo ss -tlnp | grep redis

# Test authentication
redis-cli -h 127.0.0.1 -a YourStrongPassword123! ping

# Xem thông tin server
redis-cli -a YourStrongPassword123! info server | grep -E "redis_version|uptime|connected_clients"

Tùy chọn: Giới hạn tài nguyên qua systemd

Một lớp kiểm soát nữa đáng thêm — giới hạn ở cấp systemd phòng khi Redis gặp memory leak hay bị flood request:

sudo systemctl edit redis

Thêm nội dung:

[Service]
LimitNOFILE=65535
MemoryMax=512M
sudo systemctl daemon-reload
sudo systemctl restart redis

Ba lớp bảo vệ — SELinux, firewalld và password authentication — bổ sung cho nhau. Bỏ bất kỳ lớp nào cũng tạo ra điểm yếu không cần thiết. Mất thêm 15 phút setup đúng từ đầu thì đỡ mất 2 tiếng debug lúc 2 giờ sáng.

Share: