Redis mặc định không có mật khẩu, không mã hoá, và mọi khách đều làm được mọi thứ. Bài này đo hai lớp bảo vệ và cái giá thật của từng lớp.

Kết quả kiểm tra ACL và bảng đo chi phí TLS

ACL: chặn theo lệnh và theo mẫu khoá cùng lúc

ACL SETUSER doc on >mk1 ~bo-dem:* +get +mget +exists

Kết quả khi đăng nhập bằng người dùng đó:

GET bo-dem:x    ->  v
GET khac:y      ->  NOPERM No permissions to access a key
SET bo-dem:x    ->  NOPERM ... no permissions to run the 'set' command
DEL bo-dem:x    ->  NOPERM ... 'del'
FLUSHALL        ->  NOPERM ... 'flushall'
CONFIG GET      ->  NOPERM ... 'config|get'

Hai loại chặn hoàn toàn khác nhau, và hai thông báo khác nhau — bạn biết ngay là thiếu quyền lệnh hay thiếu quyền khoá.

Chú ý dòng cuối: quyền phân tới mức lệnh con (config|get tách khỏi config|set). Đây là mức chi tiết mà requirepass không có.

Cú pháp đáng nhớ:

Ký hiệu Nghĩa
~mau:* Khoá khớp mẫu này
+lenh / -lenh Cho phép / cấm một lệnh
+@read, +@write, +@admin Cả nhóm lệnh
+@all / -@all Tất cả / không gì
&kenh:* Kênh Pub/Sub
on / off Bật hoặc tắt người dùng

Người dùng default mặc định là ~* &* +@allkhông có mật khẩu. Đây là điều đầu tiên nên sửa:

ACL SETUSER default off
ACL SETUSER app on >mat-khau-manh ~app:* +@read +@write

Tắt default thay vì đặt mật khẩu cho nó — như vậy mọi kết nối buộc phải khai danh tính rõ ràng.

TLS: đắt lúc bắt tay, gần miễn phí lúc chạy

Thường TLS Chênh
Bắt tay + PING (p50) 0,164 ms 1,062 ms ×6,5
Thông lượng, không đường ống 18.789/s 16.626/s −11,5%
Thông lượng, đường ống 100 461.274/s 477.027/s bằng nhau
CPU máy chủ cùng tải 38,71% 54,26% +40%

Dòng thứ ba là điều bất ngờ: có đường ống, TLS không chậm hơn chút nào — 477.027 so với 461.274, chênh lệch nằm trong nhiễu.

Lý do: chi phí mã hoá tính trên bản ghi TLS, không trên từng lệnh. Một lô 100 lệnh đi trong vài bản ghi, và phần mã hoá nhỏ hơn nhiều so với công việc Redis phải làm để xử lý 100 lệnh.

Không có đường ống thì mỗi lệnh là một bản ghi riêng, và 11,5% là chi phí đó.

Nhưng CPU tăng thật

38,71% lên 54,26% cho cùng một lượng công việc.

Với Redis chạy một luồng, đó là 40% trần năng lực bị ăn mất. Thông lượng tối đa của bạn giảm tương ứng — bạn chỉ không thấy điều đó cho tới khi chạm trần.

Và bắt tay chậm 6,5 lần cộng dồn với kết quả ở phần 31: mở kết nối mới mỗi lệnh vốn đã chậm 5,5 lần, thêm TLS thì tệ hơn nữa. Bể kết nối chuyển từ tuỳ chọn sang bắt buộc.

Ba lớp, theo thứ tự đáng làm

1. Đừng để Redis nghe trên mạng công khai. Rẻ nhất và hiệu quả nhất:

bind 127.0.0.1 10.0.1.5
protected-mode yes

Phần lớn sự cố Redis bị xâm nhập không phải do mật khẩu yếu mà do cổng 6379 mở ra Internet. Redis 3.2 trở đi có protected-mode chặn kết nối ngoài khi chưa đặt mật khẩu, nhưng đừng dựa vào nó — hãy khai bind cho đúng.

2. ACL cho từng ứng dụng. Miễn phí về hiệu năng, và nó chặn được lớp lỗi lớn nhất: một dịch vụ gọi FLUSHALL vì lập trình viên gõ nhầm, hoặc một dịch vụ đọc dữ liệu của dịch vụ khác.

Đặc biệt đáng cấm: FLUSHALL, FLUSHDB, CONFIG, DEBUG, SHUTDOWN, KEYS. Cái cuối không vì bảo mật mà vì lý do đo được ở phần 11.

3. TLS khi lưu lượng đi qua mạng không tin cậy. Trong một VPC riêng, cân nhắc; qua Internet, bắt buộc.

Vài chi tiết khi bật TLS

Cổng riêng. tls-port 6380 tách khỏi port 6379. Đặt port 0 để tắt hẳn cổng không mã hoá — nếu không, ai cũng có thể bỏ qua TLS.

tls-auth-clients mặc định yes, tức khách phải có chứng chỉ. Trong phép đo tôi đặt no cho gọn, nhưng yes mới là cấu hình đúng: nó biến TLS từ "mã hoá đường truyền" thành "xác thực hai chiều".

Bản sao và Cluster cần cấu hình riêng. tls-replication yestls-cluster yes — thiếu chúng thì lưu lượng nhân bản vẫn đi bằng văn bản rõ, và đó là toàn bộ dữ liệu của bạn.

Chứng chỉ hết hạn làm sập cụm. Redis không tự nạp lại chứng chỉ; cần CONFIG SET tls-cert-file ... hoặc khởi động lại. Đặt lịch nhắc.

Cái ACL và TLS không bảo vệ

Nhắc lại từ các phần trước, vì nó dễ bị bỏ qua khi đã bật bảo mật:

  • ACL không ngăn được KEYS làm nghẽn máy chủ nếu bạn cho phép nó (phần 11).
  • TLS không ngăn được một khách đọc chậm chiếm 200 MB bộ đệm (phần 30).
  • Cả hai đều không thay thế được maxmemory và giới hạn bộ đệm đầu ra.

Bảo mật và ổn định là hai trục khác nhau, và Redis mặc định yếu ở cả hai.

Thử ba mươi giây

Kiểm ba thứ dễ sai nhất:

redis-cli acl list
redis-cli acl whoami
redis-cli config get bind protected-mode port tls-port | paste - -

Ba dấu hiệu:

  • user default on nopass ~* &* +@all — bất kỳ ai kết nối được đều làm được mọi thứ, kể cả FLUSHALL.
  • bind0.0.0.0 hoặc trống — Redis đang nghe trên mọi giao diện.
  • port khác 0 trong khi tls-port đã đặt — cổng không mã hoá vẫn mở, và TLS của bạn là tuỳ chọn chứ không phải bắt buộc.

Phần sau: theo dõi Redis — chỉ số nào đáng cảnh báo và chỉ số nào gây hiểu nhầm.