Thứ Bảy, 5 tháng 3, 2022

Phần 3: Bảo mật cho redis. (redis security)

Phần 3: Bảo mật cho redis. (redis security)

Seri Redis của chúng ta gồm những phần sau:

Phần 1: Cài đặt redis cơ bản + Turning redis.
Phần 2: Lệnh quản trị redis cơ bản
Phần 3: Bảo mật cho redis. (redis security)
Phần 4: Access List Redis (tính năng mới từ bản 6)
Phần 5: Các mô hình Redis replication, Ưu và nhược điểm
Phần 6: Redis Master-Salve sử dụng ACL
Phần 7: Redis Sentinel sử dụng ACL
Phần 8: Cài đặt Redis Cluster
Phần 9: Di chuyển data từ redis đơn sang cluster và ngược lại.
Phần 10: Data type trong Redis, một vài ví dụ sử dụng (String/hash/sort/list/queue/pub-sub....).
Phần 11: Một số lỗi thường gặp khi quản trị hệ thống Redis.
Phần 12: Continue...

Phần 3: Bảo mật cho redis. (redis security)

Trên thế giới, có rất nhiều vụ redis phơi port ra ngoài bị chiếm quyền điều khiển để cài miner, hoặc xóa sạch dữ liệu redis, thay đổi dữ liệu để trục lợi. Vì vậy ta luôn sẵn tinh thần bảo mật cho redis:

1. Thay đổi Port

Thay đổi port để tránh bị scan tấn công:

[root@master-node ~]# /etc/init.d/redis_6379 stop
[root@master-node ~]# cat /opt/redis/conf/6379.conf  | grep 'port 6379'
port 6379
[root@master-node ~]# cat /etc/init.d/redis_6379 | grep REDISPORT
REDISPORT="6379"

# VD ta đổi thành port 6800, cần đổi ở trong file config và file khởi động.
[root@master-node ~]# vi /opt/redis/conf/6379.conf 
port 6800
[root@master-node ~]# vi /etc/init.d/redis_6379
REDISPORT="6800"

#Kiểm tra:
[root@master-node ~]# ps aux | grep redis | grep server
root      97040  0.1  0.1 165072  3032 ?        Ssl  13:09   0:00 /usr/local/bin/redis-server 127.0.0.1:6800
[root@master-node ~]# redis-cli -h 127.0.0.1 -p 6800 INFO

2. Chặn firewall

  • Nếu bạn chạy app và redis chung 1 server, giữ nguyên bind 127.0.0.1, Port redis chỉ lắng nghe nội bộ nên khá an toàn.
  • Trường hợp App và redis nằm ở riêng 2 server khác nhau, ta để bind 0.0.0.0 nhưng chú ý Chặn Firewall hoặc chặn network ở mạng nội bộ DMZ.

Cách public port redis như sau:

[root@master-node ~]# cat /opt/redis/conf/6379.conf | grep bind | grep -v '#'
bind 127.0.0.1 -::1
Sửa thành bind 0.0.0.0 . Và chú ý về Firewall, chặn không cho bên ngoài tấn công.

3. Đặt mật khẩu cho redis

Có 2 cách đặt mật khẩu, bản redis 6 ra tính năng mới ra ACL, mình khuyến khích các bạn dùng ACL này về sau. Các phần tiếp theo tôi sẽ hướng dẫn các bạn sử dụng thành thạo ACL.

[root@master-node conf]# redis-cli -p 6800
127.0.0.1:6800> ACL SETUSER default on >matkhau ~* &* +@all
OK
127.0.0.1:6800> CONFIG REWRITE
OK
[root@master-node conf]# redis-cli --user default --pass matkhau -p 6800 INFO
Ta kiểm tra config sẽ có thêm 1 dòng sau:
[root@master-node conf]# cat /opt/redis/conf/6379.conf | grep 'user default'
user default on #6445e373d7fcde106bfcb897ee8f0bb28589bd7797f54f1ef4e5d5447cfbd011 ~* &* +@all

Sửa lại init file, nếu không sửa bạn sẽ không bật tắt đc redis bằng init/systemd:
[root@master-node conf]# vi /etc/init.d/redis_6379  | grep cli
CLIEXEC="/usr/local/bin/redis-cli --user default --pass matkhau"

Cách 2: Không sử dụng ACL (không khuyến khích về sau, dùng cho các thư viện code cũ, bạn phải đảm bảo trong config đang không dùng ACL)

[root@master-node conf]# cat /opt/redis/conf/6379.conf | grep 'user default'
user default on #64xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe5d5447cfbd011 ~* &* +@all
Nếu có dòng này, bạn hãy comment # lại. Vì nếu ACL cách 1 đã có, thì cách 2 ở dưới bị vô hiệu.

Sửa config như sau: 
[root@master-node conf]# vi /opt/redis/conf/6379.conf
requirepass "matkhau"

Kiểm tra:
[root@master-node conf]# redis-cli -p 6800 -a matkhau INFO

Sửa init file: 
[root@master-node conf]# vi /etc/init.d/redis_6379  | grep cli
CLIEXEC="/usr/local/bin/redis-cli -a matkhau"

4. Xóa những lệnh nguy hiểm

Liệt kê những lệnh nguy hiểm (chỉ dành cho quản lý redis, không dành cho role dev, app):

127.0.0.1:6379> ACL CAT dangerous
 1) "replconf"
 2) "restore"
 3) "cluster"
 4) "pfdebug"
 5) "bgrewriteaof"
 6) "latency"
 7) "acl"
 8) "swapdb"
 9) "info"
10) "replicaof"
11) "migrate"
12) "flushall"
13) "flushdb"
14) "lastsave"
15) "keys"
16) "save"
17) "config"
18) "pfselftest"
19) "restore-asking"
20) "slaveof"
21) "sync"
22) "failover"
23) "debug"
24) "slowlog"
25) "role"
26) "module"
27) "psync"
28) "sort"
29) "client"
30) "monitor"
31) "bgsave"
32) "shutdown"

Thay command nguy hiểm xóa hết dữ liệu hoặc làm giảm hiệu năng redis. Ta sửa config như sau:

[root@master-node conf]# tail /opt/redis/conf/6379.conf
rename-command FLUSHALL XOAHETDATA
rename-command FLUSHDB XOADATADBHIENTAI
[root@master-node conf]# redis-cli -p 6800
127.0.0.1:6800> flushall
(error) ERR unknown command `flushall`, with args beginning with:   > OK , đã xóa lệnh flushall

5 Không cho redis chạy quyền root.

Với hệ thống dùng Systemd ta thêm User và Group=redis như sau:

[root@master-node ~]# adduser redis --no-create-home
[root@master-node ~]# vi /etc/systemd/system/redis.service
[Unit]
Description=Redis data structure server
Documentation=https://redis.io/documentation
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-server /opt/redis/conf/6379.conf --supervised systemd --daemonize no
ExecStop=/usr/local/bin/redis-cli SHUTDOWN
#ExecStop=/usr/local/bin/redis-cli --user default --pass matkhau SHUTDOWN
LimitNOFILE=10032
User=redis
Group=redis

[Install]
WantedBy=multi-user.target

Với hệ thống dùng init file ta chạy thẳng start bằng user redis.

[root@master-node ~]# /etc/init.d/redis_6379 stop
[root@master-node ~]# adduser redis --no-create-home
[root@master-node ~]# chown -R redis.root /opt/redis
[root@master-node ~]# chown redis.redis /etc/init.d/redis_6379
[root@master-node ~]# su - redis
-bash-4.2$ /etc/init.d/redis_6379 start
Starting Redis server..
-bash-4.2$ ps aux | grep redis
redis     85679  0.3  0.1 162512  3216 ?        Ssl  08:47   0:00 /usr/local/bin/redis-server 0.0.0.0:6379

Ngoài ra , để bảo mật redis còn có các đề nghị sau đây:

  • Phân quyền chạy và đọc file tối thiểu (file chạy là 750, file log, config là 640)
  • Đặt lịch Backup log, config, dump
  • Bật TLS giữa client và redis-server.

Phần sau, tôi sẽ hướng dẫn bạn một cách khác là dùng ACL để khóa các command nguy hiểm này

Phần 2: Lệnh quản trị redis cơ bản

Phần 2: Lệnh quản trị redis cơ bản

Seri Redis của chúng ta gồm những phần sau:

Phần 1: Cài đặt redis cơ bản + Turning redis.
Phần 2: Lệnh quản trị redis cơ bản
Phần 3: Bảo mật cho redis. (redis security)
Phần 4: Access List Redis (tính năng mới từ bản 6)
Phần 5: Các mô hình Redis replication, Ưu và nhược điểm
Phần 6: Redis Master-Salve sử dụng ACL
Phần 7: Redis Sentinel sử dụng ACL
Phần 8: Cài đặt Redis Cluster
Phần 9: Di chuyển data từ redis đơn sang cluster và ngược lại.
Phần 10: Data type trong Redis, một vài ví dụ sử dụng (String/hash/sort/list/queue/pub-sub....).
Phần 11: Một số lỗi thường gặp khi quản trị hệ thống Redis.
Phần 12: Continue...

Phần 2: Làm quen lệnh quản trị redis cơ bản

MONITOR

Đây là 1 lệnh rất hay, dùng để GIÁM SÁT realtime toàn bộ hoạt động của redis (VD trong trường hợp bạn đang không biết code đang bung lệnh gì vào redis )

#redis-cli
127.0.0.1:6379> MONITOR
1645808925.291724 [0 127.0.0.1:54180] "SET" "TUANDA" "123"
1645808928.157719 [0 127.0.0.1:54180] "GET" "TUANDA"
1645808939.043673 [0 127.0.0.1:54180] "EXPIRE" "TUANDA" "5"

hoặc
[root@master-node ~]# redis-cli MONITOR

CLIENT LIST

Giúp chúng ta liệt kê có bao nhiêu client đang kết nối vào redis-server, đang chạy command gì

127.0.0.1:6379> CLIENT LIST
id=3086 addr=192.168.88.13:35764 laddr=192.168.88.12:6379 fd=10 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=40954 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=61464 events=r cmd=set user=default redir=-1

Như trên ta thấy client có IP là 192.168.88.13:35764 đang kết nối đến server 192.168.88.12:6379 và sử dụng command cmd=SET để ghi key vào redis.

Lệnh này rất thuận tiện để cho ta debug rằng tiến trình / code tại server nào đang gọi + giữ kết nối nhiều đến redis server, làm tràn connection đến Redis > để báo DEV kiểm tra và fix close connection.

INFO

Show toàn bộ status của redis, bao gồm CPU/RAM/KEY. Các công cụ giám sát như prometheus, zabbix, nagios... đều dùng lệnh này để lấy giá trị ra giám sát:

# Clients
connected_clients:2
cluster_connections:0
maxclients:20000
# Memory
used_memory:1435904
# Replication
role:master
connected_slaves:0
#Keyspace
db0:keys=2,expires=0,avg_ttl=0

SCAN thay vì dùng KEYS

Lệnh KEYS * tốt khi dùng redis với ít key-value. Nhưng khi có vài triệu key thì KEYS * không phải là lựa chọn tốt (gây ra cao tải I/O, lệnh keys bị cấm ở Prod). Thay vào đó ta có các lựa chọn khác

- Search 5000 key ngẫu nhiên
"scan" "0" "MATCH" "*" "COUNT" "500"

- Search 1 key ngẫu nhiên
RANDOMKEY

- HOẶC dùng regex
KEYS ABC*

CONFIG GET / CONFIG SET

Chức Năng: Lấy thông tin cấu hình của redis đang chạy, phù hợp với sysadmin mới tiếp nhận redis, sẽ hiểu được toàn bộ cấu hình đang chạy. (Ví dụ: log nằm ở đâu, file rdb dump (dữ liệu) nằm ở đâu, thời gian bgsave như nào )

127.0.0.1:6379> CONFIG GET maxclients
"20000"
127.0.0.1:6379> CONFIG SET maxclients 100000
OK
127.0.0.1:6379> CONFIG GET *
hoặc
[root@master-node ~]# redis-cli  CONFIG GET "*"

SLOWLOG GET

Hiển thị các command chiếm I/O của redis

127.0.0.1:6379> SLOWLOG help
127.0.0.1:6379> SLOWLOG GET

SELECT

Chắc ít bạn sẽ biết là redis có tận 16 vùng chứa db khác nhau. Mặc dịnh tất cả các thao tác nằm ở db0. Lệnh select giúp chúng ta chuyển Namespace (giống với k8s). Dữ liệu của mỗi namespace sẽ không liên quan tới nhau, ta có thể đặt trùng tên. Dùng để tách biệt môi trường ví dụ 2 key giống tên nhau mà có value khác nhau.

BGSAVE / SAVE

Cập nhập mới toàn bộ data trên ram của redis vào dump.rdb file. (Phục vụ cho công việc upgrade redis version, restart redis node... để tránh mất dữ liệu trên ram)

- BGSAVE: 
BackGround save. Lưu toàn bộ dữ liệu thay đổi của redis được ghi đồng thời, không ảnh hưởng đến hoạt động của redis-server.
- SAVE: 
Redis sẽ LOCK toàn bộ command tác động đến dữ liệu và tiến hành lưu dữ liệu vào rdb.

Backup/Clone dữ liệu redis:

Redis lưu toàn bộ dữ liệu trên file dump.rdb, để clone dữ liệu sang 1 redis khác, có 2 cách:

  • Để redis mới thành slave của con đang chạy, sau đó ngắt slave và cho chạy làm Master.
  • Copy offline file dump.rdb, để vào thư mục data của redis mới, start redis mới là ta đã clone thành công.

Other, Sử dụng pipeline để export/import toàn bộ Key/Value (String) của redis.

(Chỉ sử dụng cho redis đang lưu String, dành cho ai cần đến, Hash/List/Sort/ZSET.. không áp dụng đc) Để import ta có thể chuẩn bị file mẫu như sau:

vi import.txt
SET TUANDA1 1231
SET TUANDA2 1232
EXPIRE TUANDA1 1001
EXPIRE TUANDA2 1002
[root@master-node ~]# redis-cli < import.txt
[root@master-node ~]# redis-cli GET TUANDA1
"1231"
[root@master-node ~]# redis-cli TTL TUANDA1
(integer) 971

Để export toàn bộ key String ta có thể làm cách sau:

[root@master-node ~]# redis-cli KEYS "*" > key_export.txt
[root@master-node ~]# cat key_export.txt 
TUANDA1
TUANDA
TUANDA2
[root@master-node ~]# sed -i -e 's/^/GET /g' key_export.txt 
[root@master-node ~]# cat key_export.txt 
GET TUANDA1
GET TUANDA
GET TUANDA2
[root@master-node ~]# redis-cli < key_export.txt > value_export.txt
[root@master-node ~]# cat value_export.txt 
1231
123
1232
[root@master-node ~]# paste key_export.txt value_export.txt 
GET TUANDA1	1231
GET TUANDA	123
GET TUANDA2	1232

Phần 1: Cài đặt redis cơ bản + Turning redis.

Phần 1: Cài đặt redis cơ bản + Turning redis.

Seri Redis của chúng ta gồm những phần sau:

Phần 1: Cài đặt redis cơ bản + Turning redis.
Phần 2: Lệnh quản trị redis cơ bản
Phần 3: Bảo mật cho redis. (redis security)
Phần 4: Access List Redis (tính năng mới từ bản 6)
Phần 5: Các mô hình Redis replication, Ưu và nhược điểm
Phần 6: Redis Master-Salve sử dụng ACL
Phần 7: Redis Sentinel sử dụng ACL
Phần 8: Cài đặt Redis Cluster + kiểm tra cluster hoạt động.
Phần 9: Thêm và xóa node redis cluster, di chuyển data đơn sang cluster và ngược lại
Phần ??: Data type trong Redis, một vài ví dụ sử dụng (String/hash/sort/list/queue/pub-sub....).
Phần ??: Một số lỗi thường gặp khi quản trị hệ thống Redis.
Phần ??: Redis RDB và AOF nên chọn cái nào?

(Các phần của mình viết sẽ khó hiểu và phức tạp hơn trên mạng 1 chút, vì sẽ chuyên sâu cho System+Dev quản trị redis)

Phần 1: Cài đặt redis cơ bản + Turning redis.

1.1 Cài đặt:

(Sao không cài yum hoặc apt mà lại cài từ tar.gz: Vì dễ quản lý file và config về sau, thuận tiện cho việc backup data file/config/logs/quản lý phân vùng lưu trữ, upgrade version...)

Bước 1: Tải redis từ trang chủ: https://redis.io/download . các bạn cứ chọn bản mới nhất mà cài. Vì redis build rất ổn định (update 7.0.8 - 2023-01-20).

Bản mới nhất (2023-01) 
# yum install gcc wget systemd-devel -y
# mkdir -p /opt/setup
# cd /opt/setup
# wget https://github.com/redis/redis/archive/7.0.8.tar.gz
# tar -xvzf 7.0.8.tar.gz
# cd redis-7.0.8
# make
Khi make install, các file chạy binary sẽ được copy sang thư mục /usr/local/bin/
# make install

Khi make install, câu lệnh sẽ thực hiện copy các file chạy redis gồm (redis-server , redis-benchmark , redis-cli ) vào thư mục /usr/local/bin/

Bước 2: Cài đặt các thư mục riêng cho redis, để quản lý về sau ( như: data , conf, log)

# mkdir -p /opt/redis/conf

# mkdir -p /opt/redis/data

# mkdir -p /opt/redis/log

# cd /opt/setup/redis-7.0.8/utils/

# vim install_server.sh (ta comment lại dòng 82 vì có exit 1 không tương thích với systemd - lỗi ko cần thiết)

Thực hiện chạy file, và khai báo như sau

$ ./install_server.sh

Tắt bật redis:

# /etc/init.d/redis_6379 status
# /etc/init.d/redis_6379 stop
# /etc/init.d/redis_6379 start
# Bạn nào muốn dùng systemd, Đọc. Phần 3: Bảo mật cho redis. (redis security) nhé.

Lệnh chạy cơ bản vào redis bằng lệnh

# redis-cli ping                           #(Dùng để kiểm tra redis alive)
# redis-cli set hello-world awesome1       #(đặt key hello-world có data value = awesome)
# redis-cli get hello-world                #(lấy giá trị value của key ra)
# redis-cli info                           #(xem thông tin status của redis)
# redis-cli config get                     #(Xem toàn bộ config của redis đang chạy)
# redis-cli monitor                        #(GIÁM SÁT các câu lệnh đang chạy real-time - RẤT hay)
# redis-cli client list                    #(Kiểm tra xem có bao nhiêu client, ip client đang kết nối, client đang dùng lệnh gì.)
# redis-cli info clients                   #(Xem số client đang kết nối tới redis server)

Ngoài việc gõ trực tiếp command trên unix. Ta có thể vào redis-cli để gõ các lệnh như sau:

[root@master-node ~]# redis-cli 
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET hello-world awmsome2
OK
127.0.0.1:6379> GET hello-world
"awmsome2"

1.2: Turning redis:

P1: Enable vm.overcommit_memory

# vim /etc/sysctl.conf
vm.overcommit_memory=1
net.core.somaxconn=65535
#sudo sysctl --system

chạy lệnh sysctl vm.overcommit_memory=1 Khi ghi dữ liệu từ RAM xuống disk, Redis sử dụng các tiến trình con. Theo mặc định, tiến trình con này cần memory tương đương tiến trình mẹ, do nó có chứa dữ liệu tương đương. Điều này dẫn tới OS không đủ RAM cho việc ghi DB xuống Disk này > lỗi. Tuy nhiên Linux có hỗ trợ Copy-on-write, nghĩa là chỉ cần cấp memory cho những gì tiến trình con khác với tiến trình mẹ, phần giống nhau thì dùng chung memory cho tiết kiệm. Để bật nó thì cần set overcommit_memory = 1

P2: net.core.somaxconn (tăng hàng đợi tối đa của linux)

sysctl -w net.core.somaxconn=65535
cat /proc/sys/net/core/somaxconn
65535

P3: Set never transparent_hugepage

Giải thích: https://kipalog.com/posts/Tinh-nang-Transparent-HugePage-trong-RHEL6-va-anh-huong

# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
# echo never > /sys/kernel/mm/transparent_hugepage/enabled


# vim /etc/rc.local (thêm vào cuối file rc.local để mỗi lần khởi động lại Linux, hugpage lại chuyển thành never)
echo never > /sys/kernel/mm/transparent_hugepage/enabled

P4: Tăng connection kết nối

Mặc định redis seting maxclients kết nối đồng thời là 10000, nếu coder tốt thì khi mở kết nối xong sẽ gọi lệnh close (cả hệ thống lớn chắc ko đến 100 kết nối đồng thời). Vẫn để phòng trường hợp quá connection khi bị miss code ở đoạn nào đó. Ta có thể tăng Maxclients lên.

Cách 1: Thay trong redis-cli

127.0.0.1:6379> CONFIG GET MAXCLIENTS
"10000"
127.0.0.1:6379> CONFIG SET MAXCLIENTS 100000
OK (thực hiện tăng maxclient tạm thời)
127.0.0.1:6379> CONFIG REWRITE
OK (Thực hiện ghi đè config hiện tại / vĩnh viễn)

Cách 2: Thay trong config

vim /opt/redis/conf/6379.conf
maxclients 100000

Mời các bạn đón đọc: Phần 2: Lệnh quản trị redis cơ bản

(Kiến thức người viết bài có thể có góc nhìn hẹp, xin các bạn góp ý đóng góp xây dựng bài.)

Nginx mTLS

  A. Nginx as SERVER with mTLS Trong  hệ thống nội bộ, ca certificate thường dùng chung cả cho server và client. Nhưng nếu bảo mật hơn, có t...