Triển khai Database theo kiến trúc an toàn
Bước đầu tiên là cài đặt PostgreSQL phiên bản ổn định mới nhất (LTS) để đảm bảo có các bản vá bảo mật mới nhất và hỗ trợ đầy đủ cho TDE cũng như Audit.
Tại sao: Sử dụng bản cập nhật mới nhất giúp giảm thiểu lỗ hổng đã biết (CVE) và đảm bảo tính tương thích với các module bảo mật sẽ được triển khai ở các phần sau.
Kết quả mong đợi: Dịch vụ PostgreSQL được cài đặt và khởi động thành công trên hệ thống.
Trên hệ thống Ubuntu/Debian, hãy chạy các lệnh sau để thêm repository chính thức và cài đặt:
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql.gpg
echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt update
sudo apt install -y postgresql-16 postgresql-contrib-16
Kiểm tra trạng thái dịch vụ sau khi cài đặt:
systemctl status postgresql
Bạn sẽ thấy trạng thái là active (running).
Cấu hình file cấu hình để chặn truy cập từ xa
Chúng ta cần chỉnh sửa file postgresql.conf để đảm bảo Database chỉ lắng nghe trên giao diện loopback (localhost), ngăn chặn truy cập từ mạng ngoài trừ khi có yêu cầu đặc biệt qua Proxy hoặc SSH Tunnel.
Tại sao: Việc để mặc định listen_addresses = '*' là lỗ hổng bảo mật lớn nhất, cho phép kẻ tấn công quét và cố gắng brute-force từ internet.
Kết quả mong đợi: PostgreSQL chỉ chấp nhận kết nối từ 127.0.0.1 và ::1.
Chỉnh sửa file cấu hình chính của PostgreSQL:
sudo nano /etc/postgresql/16/main/postgresql.conf
Tìm dòng listen_addresses và thay đổi giá trị thành localhost. Nếu dòng này bị comment, hãy bỏ comment và chỉnh sửa:
listen_addresses = 'localhost'
Đồng thời, kiểm tra port mặc định (5432) để đảm bảo không trùng với dịch vụ khác, tuy nhiên giữ nguyên 5432 là an toàn nhất nếu không có xung đột.
Sau khi lưu file, cần cấu hình file pg_hba.conf để xác định chính sách phân quyền kết nối (host-based authentication).
Chỉnh sửa file xác thực:
sudo nano /etc/postgresql/16/main/pg_hba.conf
Xóa hoặc comment tất cả các dòng bắt đầu bằng host (cho phép kết nối từ xa) và chỉ giữ lại các dòng cho phép kết nối local. Nội dung an toàn tối thiểu cần có trong file:
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
Lưu ý: peer cho kết nối local socket (chỉ dùng cho user OS), md5 (hoặc scram-sha-256 trong bản mới) yêu cầu mật khẩu cho kết nối TCP/IP từ localhost.
Khởi động lại dịch vụ để áp dụng cấu hình:
sudo systemctl restart postgresql
Kiểm tra xem server có đang lắng nghe đúng địa chỉ chưa:
sudo ss -tlnp | grep 5432
Kết quả mong đợi: Bạn chỉ thấy 127.0.0.1:5432 hoặc ::1:5432, không thấy 0.0.0.0 hay *.
Thiết lập quyền truy cập cho thư mục dữ liệu
Dữ liệu cơ sở dữ liệu (data directory) chứa toàn bộ file bin, log và index. Chúng ta cần đảm bảo chỉ user postgres mới có quyền đọc/ghi vào thư mục này, ngăn chặn user root hoặc user khác đọc trộm.
Tại sao: Nếu thư mục data có quyền 777 hoặc thuộc sở hữu của root, PostgreSQL sẽ từ chối khởi động vì lý do bảo mật (permission denied), và nguy hiểm hơn là các user khác trên máy có thể đọc dữ liệu nhạy cảm.
Kết quả mong đợi: Thư mục data chỉ có quyền 700 và thuộc sở hữu hoàn toàn của user postgres.
Xác định đường dẫn thư mục dữ liệu (data directory) hiện tại:
psql -U postgres -c "SHOW data_directory;"
Giả sử đường dẫn trả về là /var/lib/postgresql/16/main. Thực hiện lệnh thay đổi quyền sở hữu và chmod:
sudo chown -R postgres:postgres /var/lib/postgresql/16/main
sudo chmod -R 700 /var/lib/postgresql/16/main
Cũng cần đảm bảo thư mục log (thường nằm ở /var/log/postgresql) cũng có quyền đúng:
sudo chown -R postgres:postgres /var/log/postgresql
sudo chmod 750 /var/log/postgresql
Verify kết quả bằng lệnh ls -ld:
ls -ld /var/lib/postgresql/16/main
ls -ld /var/log/postgresql
Kết quả mong đợi: Dòng đầu tiên hiển thị drwx------ postgres postgres, dòng thứ hai hiển thị drwxr-x--- postgres postgres.
Tạo user quản trị và xóa user mặc định
Chúng ta cần tạo một tài khoản quản trị viên (superuser) mới với mật khẩu mạnh để thay thế tài khoản mặc định postgres hoặc hạn chế quyền của nó, đồng thời xóa các user test hoặc guest không cần thiết.
Tại sao: Tài khoản mặc định postgres thường bị các script tự động hóa hoặc công cụ scan dò tìm. Việc tạo user mới và vô hiệu hóa user mặc định giúp giảm bề mặt tấn công.
Kết quả mong đợi: Có một user quản trị mới (ví dụ: admin_db) và user postgres không còn quyền đăng nhập qua mạng hoặc bị vô hiệu hóa.
Đầu tiên, đăng nhập vào shell của user postgres để tạo user mới:
sudo -i -u postgres
Tạo user quản trị mới với quyền superuser và yêu cầu phải đặt mật khẩu:
createuser --superuser --pwprompt admin_db
Hệ thống sẽ yêu cầu bạn nhập mật khẩu và xác nhận lại. Hãy nhập một mật khẩu phức tạp.
Tiếp theo, để xóa quyền đăng nhập của user mặc định postgres qua giao thức TCP/IP (ngăn chặn đăng nhập từ xa bằng user mặc định), ta chỉnh sửa lại pg_hba.conf để chỉ cho phép user admin_db kết nối qua host.
Mở lại file pg_hba.conf:
nano /etc/postgresql/16/main/pg_hba.conf
Thêm dòng cụ thể cho user admin_db vào cuối phần host, và đảm bảo dòng mặc định cho user postgres không nằm ở phần host:
host all admin_db 127.0.0.1/32 scram-sha-256
host all all 127.0.0.1/32 reject
Lưu ý: Dòng reject ở cuối sẽ chặn mọi user khác (bao gồm postgres) khi cố kết nối qua TCP/IP từ localhost, chỉ cho phép admin_db (hoặc các user bạn thêm trước dòng reject).
Nếu muốn xóa hoàn toàn user mặc định postgres khỏi database (cần thận trọng, chỉ làm nếu đã sao lưu và có user mới):
dropuser postgres
Tuy nhiên, an toàn hơn là chỉ vô hiệu hóa quyền đăng nhập như đã cấu hình trong pg_hba.conf ở trên để tránh lỗi hệ thống phụ thuộc vào user này.
Khởi động lại dịch vụ để áp dụng thay đổi về user:
exit
sudo systemctl restart postgresql
Verify kết quả bằng cách thử kết nối với user mới:
psql -h 127.0.0.1 -U admin_db -d postgres
Hệ thống sẽ yêu cầu nhập mật khẩu của admin_db. Nếu thành công, bạn sẽ thấy prompt postgres=#.
Thử kết nối với user mặc định (nên bị chặn nếu cấu hình đúng):
psql -h 127.0.0.1 -U postgres -d postgres
Kết quả mong đợi: Lệnh trên sẽ trả về lỗi FATAL: no pg_hba.conf entry for host... hoặc password authentication failed tùy cách cấu hình reject.
Điều hướng series:
Mục lục: Series: Triển khai Database An toàn với TDE, Audit và Linux Kernel Hardening
« Phần 2: Hardening Linux Kernel: Bảo vệ nền tảng hệ điều hành
Phần 4: Triển khai TDE (Transparent Data Encryption) cho dữ liệu »