Bối cảnh: Đừng phó mặc database cho tường lửa
Nhiều kỹ sư hạ tầng vẫn giữ thói quen chỉ đổi port 3306 hoặc dựng iptables/UFW rồi coi như database đã an toàn. Thực tế tàn khốc hơn nhiều. Khi một web app trong cùng dải mạng nội bộ dính lỗ hổng SSRF hay RCE, con đường từ web server tới MySQL gần như mở toang.
Một hệ thống database đạt chuẩn PCI-DSS hay ISO 27001 bắt buộc phải kiểm soát chặt chẽ ba phòng tuyến sống còn:
- Dữ liệu truyền tải (Data-in-Transit): Nếu không bật SSL/TLS, backend và database trao đổi hoàn toàn bằng cleartext. Kẻ nghe lén trên switch hoặc qua container lân cận chỉ cần chạy
tcpdumplà hớt trọn credentials lẫn dữ liệu giao dịch nhạy cảm. - Dữ liệu lưu trữ (Data-at-Rest): Giả sử hacker lấy được bản backup
.sqlhoặc snapshot ổ NVMe của VPS. Họ chỉ cần chạy lệnhstringstrên các file tablespace.ibdlà bóc tách được toàn bộ dữ liệu mà không cần biết mật khẩu root. - Ghi vết & Tuân thủ (Auditing): Khi dữ liệu biến mất vào giữa đêm, nếu thiếu log truy vấn chi tiết, bạn sẽ mù tịt. Ai đã chạy lệnh xóa? Từ địa chỉ IP nào? Thời điểm chính xác ra sao?
Khâu then chốt đầu tiên là gia cố tài khoản quản trị. Mình luôn dùng password generator tại toolcraft.app/vi/tools/security/password-generator để sinh mật khẩu 24-32 ký tự gồm chữ hoa, chữ thường, số và ký tự đặc biệt. Công cụ chạy thuần client-side trên trình duyệt nên không lo mật khẩu bị đẩy lên máy chủ bên ngoài. Tuyệt đối không dùng lại mật khẩu cũ cho tài khoản root MySQL hay user ứng dụng.
Chuẩn bị môi trường & Phân quyền thư mục
Môi trường thực hành trong bài là Ubuntu Server 22.04 LTS chạy MySQL 8.0.36. Nếu dùng Rocky Linux 9 hay RHEL, file cấu hình chính sẽ nằm tại /etc/my.cnf thay vì /etc/mysql/mysql.conf.d/mysqld.cnf.
1. Thiết lập thư mục lưu chứng chỉ và keyring
Chứng chỉ TLS và master key của InnoDB cần được bảo vệ ở cấp độ file system. User mysql phải là thực thể duy nhất có quyền đọc ghi:
# Thư mục chứa chứng chỉ TLS (nếu bạn tự cấp phát riêng)
sudo mkdir -p /etc/mysql/certs
sudo chown -R mysql:mysql /etc/mysql/certs
sudo chmod 700 /etc/mysql/certs
# Thư mục an toàn chứa Master Key của InnoDB
sudo mkdir -p /var/lib/mysql-keyring
sudo chown -R mysql:mysql /var/lib/mysql-keyring
sudo chmod 700 /var/lib/mysql-keyring
2. Khởi tạo cặp chứng chỉ TLS/SSL
MySQL cung cấp tiện ích mysql_ssl_rsa_setup giúp sinh nhanh cặp chứng chỉ tự ký (self-signed). Chạy lệnh sau nếu thư mục data chưa có sẵn chứng chỉ:
sudo mysql_ssl_rsa_setup --datadir=/var/lib/mysql --uid=mysql
Lệnh trên sẽ tự động tạo đủ bộ file ca.pem, server-cert.pem, server-key.pem, client-cert.pem và client-key.pem trong thư mục /var/lib/mysql.
Cấu hình chi tiết: TLS, Encryption & Audit Log
1. Bắt buộc mã hóa toàn bộ kết nối (TLS v1.2 & v1.3)
Mở file cấu hình chính của MySQL Server:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Bổ sung các directive sau vào block [mysqld] để vô hiệu hóa hoàn toàn TLS 1.0 và 1.1 vốn đã nhiều lỗ hổng:
[mysqld]
# Đường dẫn chứng chỉ và private key
ssl_ca = /var/lib/mysql/ca.pem
ssl_cert = /var/lib/mysql/server-cert.pem
ssl_key = /var/lib/mysql/server-key.pem
# Chỉ cho phép giao thức TLS an toàn
tls_version = TLSv1.2,TLSv1.3
# Từ chối mọi kết nối không dùng SSL/TLS
require_secure_transport = ON
Tham số require_secure_transport = ON là chốt chặn triệt để. Bạn không cần sửa từng user bằng quyền REQUIRE SSL. Server sẽ tự động từ chối ngay lập tức bất kỳ client nào cố tình kết nối dạng unencrypted.
2. Kích hoạt InnoDB Tablespace Encryption (Data-at-Rest)
MySQL sử dụng kiến trúc hai tầng khóa (two-tier encryption) để mã hóa dữ liệu trên đĩa mà không làm gián đoạn ứng dụng. Tablespace Key nằm ở header file .ibd và được mã hóa bằng Master Key trong file keyring. Ta dùng plugin keyring_file mặc định.
Khai báo tiếp các dòng sau vào block [mysqld] trong file mysqld.cnf:
# Nạp plugin keyring ngay khi daemon MySQL khởi động
early-plugin-load = keyring_file.so
keyring_file_data = /var/lib/mysql-keyring/keyring
# Tự động mã hóa bảng mới tạo và toàn bộ log giao dịch
default_table_encryption = ON
innodb_undo_log_encrypt = ON
innodb_redo_log_encrypt = ON
Lưu file và khởi động lại dịch vụ để áp dụng thay đổi:
sudo systemctl restart mysql
Với các bảng dữ liệu đã tồn tại từ trước, bạn cần chạy lệnh ALTER TABLE để mã hóa:
-- Mã hóa bảng users trong database app_production
ALTER TABLE app_production.users ENCRYPTION='Y';
-- Kiểm tra danh sách bảng đã được mã hóa trên server
SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS
FROM INFORMATION_SCHEMA.TABLES
WHERE CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%';
3. Cài đặt Percona Audit Plugin theo dõi truy vấn
Tính năng audit của bản MySQL Enterprise có giá bản quyền lên tới hơn 5.000 USD mỗi năm. May mắn là Percona cung cấp plugin audit mã nguồn mở miễn phí, hỗ trợ xuất log JSON và tương thích hoàn toàn với MySQL Community 8.0.
Tải thư viện audit_log.so tương ứng với phiên bản MySQL và chép vào thư mục plugin (thường là /usr/lib/mysql/plugin/). Sau đó thêm cấu hình vào mysqld.cnf:
[mysqld]
plugin_load_add = audit_log.so
audit_log_format = JSON
audit_log_policy = ALL
audit_log_file = /var/log/mysql/audit.log
audit_log_rotate_on_size = 50M
audit_log_rotations = 5
Khởi tạo file log và phân quyền trước khi reload dịch vụ:
sudo touch /var/log/mysql/audit.log
sudo chown mysql:mysql /var/log/mysql/audit.log
sudo chmod 640 /var/log/mysql/audit.log
sudo systemctl restart mysql
Kiểm thử & Giám sát thực tế
1. Kiểm tra trạng thái mã hóa kênh truyền (TLS)
Đăng nhập vào MySQL Console để kiểm tra cipher và protocol của session hiện tại:
SHOW STATUS LIKE 'Ssl_cipher';
SHOW STATUS LIKE 'Ssl_version';
Nếu kết quả trả về TLS_AES_256_GCM_SHA384 và TLSv1.3, kênh truyền đã được bảo vệ tối đa. Thử kết nối từ xa bằng cờ không mã hóa để đảm bảo server từ chối đúng như thiết lập:
mysql -u app_user -p -h 192.168.1.100 --ssl-mode=DISABLED
# Kết quả mong đợi: ERROR 3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.
2. Kiểm chứng dữ liệu mã hóa bằng lệnh strings
Cách kiểm chứng dữ liệu có thực sự được mã hóa trên đĩa hay không là đọc trực tiếp file binary .ibd:
# Tìm dữ liệu người dùng bên trong file tablespace
sudo strings /var/lib/mysql/app_production/users.ibd | grep -i "[email protected]"
Trên bảng chưa mã hóa, lệnh này sẽ in ra hàng loạt email hoặc số điện thoại rõ mồn một. Khi đã bật ENCRYPTION='Y', lệnh grep hoàn toàn im lặng vì dữ liệu đã thành các khối ciphertext AES-256. Nhờ tập lệnh phần cứng AES-NI trên các CPU hiện đại, độ trễ CPU bổ sung chỉ dao động khoảng 2-4%.
Một nguyên tắc sống còn: hãy sao lưu file /var/lib/mysql-keyring/keyring ra một máy chủ lưu trữ độc lập. Mất file keyring đồng nghĩa với việc toàn bộ dữ liệu mã hóa vĩnh viễn không thể phục hồi.
3. Đọc log điều tra và kiểm tra tính toàn vẹn file
File log audit xuất ra định dạng JSON từng dòng (JSON Lines). Bạn có thể theo dõi realtime qua lệnh tail -f:
sudo tail -n 20 /var/log/mysql/audit.log
Cấu trúc một bản ghi audit JSON chuẩn:
{"timestamp":"2026-10-16T11:45:12 UTC","id":1,"class":"general","event":"query","connection_id":24,"account":{"user":"app_user","host":"192.168.1.50"},"status":0,"sqltext":"SELECT * FROM sensitive_orders WHERE status = 'PENDING'"}
Trên hệ thống chịu tải 1.000 QPS, log audit có thể phình to 5-10 GB mỗi ngày. Cấu hình xoay vòng audit_log_rotate_on_size = 50M giúp ổ cứng không bị đầy bất ngờ.
Khi điều tra vết hack (forensics), bạn sẽ phải lọc qua hàng chục nghìn dòng log phức tạp. Mình thường dùng công cụ JSON Formatter & Validator tại toolcraft.app/vi/tools/developer/json-formatter để format và kiểm tra cú pháp payload log. Công cụ chạy 100% trong trình duyệt. Nhờ vậy, thông tin khách hàng nhạy cảm nằm trong SQL text không bao giờ bị lộ ra ngoài.
Bước cuối cùng là bảo vệ file backup và keyring khi chuyển sang máy chủ dự phòng (DR Site). Bạn nên dùng Hash Generator tại toolcraft.app/vi/tools/developer/hash-generator để tính trước mã băm SHA-256 checksum. Đối soát lại mã hash sau khi truyền file giúp bạn biết chắc dữ liệu không bị lỗi bit hay bị can thiệp trái phép trên đường truyền.
Ba lớp rào chắn: TLS 1.3 trên đường truyền, InnoDB Encryption dưới ổ đĩa và Percona Audit Log tại tầng ứng dụng tạo nên tư thế phòng thủ chiều sâu vững chắc. Cụm database của bạn giờ đây đủ sức đứng vững trước các đợt rà quét nội bộ lẫn các cuộc kiểm toán an ninh khắt khe.

