Secure Ubuntu Server cho Web Hosting: Khóa chặt Nginx, PHP, MySQL

01/05/2026 · P T P · Chung

Vì sao một Ubuntu server “chạy được web” chưa bao giờ là đủ an toàn?

Rất nhiều website bị tấn công không phải vì có lỗ hổng “quá lớn”, mà vì server được cấu hình theo kiểu mặc định là xong: mở quá nhiều dịch vụ, Nginx lộ thông tin phiên bản, PHP cho phép thực thi nguy hiểm, MySQL lắng nghe từ bên ngoài, quyền file quá rộng. Với web hosting, đặc biệt khi chạy nhiều site hoặc xử lý dữ liệu khách hàng, bảo mật không thể chỉ là cài ufw rồi yên tâm.

Cách hiệu quả hơn là tiếp cận theo tư duy phòng thủ nhiều lớp. Mỗi lớp không cần hoàn hảo, nhưng khi ghép lại sẽ làm giảm đáng kể khả năng bị khai thác và hạn chế thiệt hại nếu một lớp bị xuyên thủng. Trong bài viết này, chúng ta sẽ đi theo từng lớp bảo mật trên Ubuntu server dành cho web hosting, tập trung vào Nginx, PHP và MySQL, kèm các khuyến nghị thực tế để dễ áp dụng.

Lớp 1: Cứng hóa Ubuntu trước khi nghĩ đến ứng dụng

Trước khi tối ưu Nginx hay PHP, hãy đảm bảo hệ điều hành không trở thành điểm yếu nền tảng.

Cập nhật và tối giản bề mặt tấn công

Các nguyên tắc cơ bản nhưng rất hay bị bỏ qua:

Cập nhật bảo mật định kỳ với apt update && apt upgrade hoặc bật unattended-upgrades.
Chỉ cài đúng thứ cần dùng: Nginx, PHP-FPM, MySQL, công cụ giám sát; tránh giữ lại dịch vụ thừa như FTP cũ, mail server không dùng, database phụ.
Tắt hoặc vô hiệu hóa service không cần thiết bằng systemctl disable --now.

Mỗi service chạy trên server là thêm một cổng rủi ro. Server càng gọn, khả năng bị dò quét và khai thác càng thấp.

Bảo vệ truy cập SSH

SSH gần như luôn là cổng quản trị quan trọng nhất. Nên áp dụng:

Tắt đăng nhập bằng mật khẩu, dùng SSH key.
Đổi port SSH không phải để “ẩn hoàn toàn”, mà để giảm bot scan tự động.
Tắt đăng nhập trực tiếp bằng root.
Bật Fail2ban để chặn brute-force.
Giới hạn IP quản trị nếu có thể, qua firewall.

Firewall là lớp lọc đầu tiên

Với Ubuntu, ufw đủ tốt cho đa số nhu cầu hosting:

– Chỉ mở 80, 443, và cổng SSH quản trị.
– Không public 3306 nếu MySQL chỉ dùng nội bộ.
– Không mở trực tiếp cổng PHP-FPM.

Điểm mấu chốt là: chỉ những gì thật sự phải truy cập từ Internet mới được mở.

Lớp 2: Bảo mật Nginx như lớp biên của toàn hệ thống

Nginx là thứ đầu tiên tiếp xúc với Internet, nên cấu hình của nó quyết định bạn chặn được bao nhiêu rủi ro từ ngoài vào.

Ẩn thông tin và giảm dấu vết

Mặc định, web server thường để lộ khá nhiều thông tin. Bạn nên:

– Tắt hiển thị phiên bản bằng server_tokens off;
– Loại bỏ header thừa nếu có module phù hợp
– Dùng trang lỗi tùy chỉnh thay vì phản hồi mặc định

Mục tiêu là không cung cấp miễn phí dữ liệu cho attacker về stack mà bạn đang chạy.

Ép HTTPS và cấu hình TLS đúng cách

HTTPS giờ không chỉ để “có ổ khóa”, mà còn là lớp bảo vệ phiên đăng nhập, cookie và dữ liệu form.

Các điểm cần có:

Chuyển hướng toàn bộ HTTP sang HTTPS
– Dùng TLS 1.2/1.3
– Vô hiệu các cipher yếu
– Bật HSTS sau khi chắc chắn site đã chạy ổn qua HTTPS
– Gia hạn chứng chỉ tự động với Let’s Encrypt

Ngoài ra, nên thêm các header bảo mật quan trọng:

X-Frame-Options
X-Content-Type-Options
Referrer-Policy
Content-Security-Policy nếu ứng dụng cho phép

Đây là lớp nhỏ nhưng rất giá trị trong việc giảm clickjacking, MIME sniffing và một số kiểu XSS.

Giới hạn request bất thường

Nginx có thể giúp giảm nhiều kiểu tấn công trước khi request chạm vào PHP:

Giới hạn kích thước body bằng client_max_body_size
Rate limit cho login, API nhạy cảm, hoặc XML-RPC nếu chạy WordPress
Timeout hợp lý để chống giữ kết nối lâu
– Chặn truy cập vào file nhạy cảm như .env, .git, composer.json, wp-config.php backup

Một rule đơn giản nhưng cực hữu ích là không cho thực thi PHP trong thư mục upload. Nếu attacker tải được file độc lên, họ vẫn khó biến nó thành shell.

Lớp 3: Cô lập và siết PHP để giảm thiểu hậu quả

Phần lớn website động trên Ubuntu dùng PHP-FPM. Đây thường là nơi lỗ hổng ứng dụng bị biến thành thực thi mã, nên cần siết kỹ.

Không chạy mọi website dưới cùng một user

Nếu bạn host nhiều site, đừng để tất cả cùng chạy chung một pool PHP với cùng quyền. Thay vào đó:

– Mỗi website nên có PHP-FPM pool riêng
– Mỗi pool chạy dưới user/group riêng
– Thư mục web chỉ cấp quyền đúng mức cần thiết

Lợi ích rất rõ: nếu một site bị khai thác, attacker khó lan sang site khác.

Tắt các hàm và tính năng nguy hiểm

Trong php.ini, nên xem xét:

expose_php = Off
display_errors = Off trên production
log_errors = On
allow_url_fopenallow_url_include chỉ bật nếu thật sự cần
disable_functions với các hàm nguy hiểm như exec, shell_exec, system, passthru, proc_open

Không phải mọi ứng dụng đều tương thích với danh sách chặn mạnh tay, nên cần kiểm tra trước. Nhưng nguyên tắc là: PHP không nên có quyền gọi shell nếu ứng dụng web không cần.

Giới hạn tài nguyên và đường dẫn truy cập

Bạn nên đặt giới hạn để một script lỗi không kéo sập cả server:

memory_limit
max_execution_time
max_input_vars
post_max_size
upload_max_filesize

Nếu phù hợp, dùng thêm:

open_basedir để giới hạn thư mục PHP được phép truy cập
session.cookie_httponly = On
session.cookie_secure = On khi dùng HTTPS
cgi.fix_pathinfo = 0 để tránh một số kiểu xử lý path nguy hiểm

PHP càng ít quyền, ít thời gian chạy và ít khả năng chạm ra ngoài phạm vi app, mức độ thiệt hại càng thấp khi có lỗi.

Lớp 4: Gia cố MySQL để dữ liệu không bị “mở cửa sau”

MySQL thường chứa tài sản quan trọng nhất: tài khoản, đơn hàng, thông tin khách hàng, token. Nhưng nhiều server lại để database ở trạng thái quá dễ dãi.

Chạy MySQL ở chế độ nội bộ nếu có thể

Nếu web app và database cùng một máy, hãy để MySQL chỉ lắng nghe ở 127.0.0.1. Điều này giúp:

– Không lộ cổng 3306 ra Internet
– Giảm nguy cơ brute-force từ bên ngoài
– Đơn giản hóa firewall

Chỉ bind ra mạng riêng khi thật sự cần kiến trúc nhiều máy.

Dùng tài khoản riêng, quyền tối thiểu

Một lỗi rất phổ biến là ứng dụng dùng tài khoản có quyền quá cao, thậm chí gần như root. Thay vào đó:

– Tạo một user riêng cho từng ứng dụng
– Chỉ cấp quyền cần thiết trên đúng database
– Tránh cấp GRANT, SUPER, FILE, DROP nếu không cần

Nguyên tắc quyền tối thiểu ở database quan trọng không kém ở hệ điều hành.

Chạy mysql_secure_installation nhưng đừng dừng ở đó

Script này giúp bạn:

– Đặt mật khẩu mạnh cho tài khoản quản trị
– Xóa anonymous user
– Tắt remote root login
– Xóa database test

Tuy nhiên, cần đi xa hơn:

– Bật log phù hợp để phát hiện truy vấn bất thường
– Sao lưu định kỳ và kiểm tra khả năng restore
– Mã hóa backup nếu lưu ngoài server
– Theo dõi số lần đăng nhập lỗi hoặc kết nối bất thường

Database an toàn không chỉ là “khó vào”, mà còn là khó mất dữ liệu và dễ phục hồi.

Lớp 5: Quyền file, giám sát và ứng phó sự cố

Nhiều vụ xâm nhập kéo dài hàng tuần chỉ vì admin không có log đủ tốt, hoặc quyền file cho phép sửa toàn bộ mã nguồn từ web process.

Phân quyền file đúng cách

Một mô hình phổ biến:

– File code: chỉ owner được ghi
– Web server chỉ cần quyền đọc, và ghi vào một số thư mục cụ thể như storage, cache, uploads
– Không dùng 777
– Tách rõ thư mục deploy, log và dữ liệu người dùng

Điều này giúp giảm nguy cơ web shell sửa mã nguồn hoặc cài backdoor sâu hơn.

Log và giám sát là “báo động sớm”

Bạn nên theo dõi ít nhất:

auth.log cho SSH
– access/error log của Nginx
– log PHP-FPM
– log MySQL
– cảnh báo từ Fail2ban, ufw, hoặc công cụ giám sát như Netdata/Prometheus

Không cần hệ thống SIEM quá phức tạp ngay từ đầu, nhưng phải có khả năng trả lời các câu hỏi cơ bản: ai đăng nhập, khi nào, từ đâu, request nào bất thường, tiến trình nào tiêu tốn tài nguyên.

Luôn chuẩn bị cho tình huống bị xâm nhập

Bảo mật tốt không đồng nghĩa với miễn nhiễm tuyệt đối. Hãy chuẩn bị:

– Backup tự động, lưu ở nơi khác server chính
– Kế hoạch rotate password và SSH key
– Quy trình cách ly site bị nhiễm
– Checklist rà soát: cron lạ, file mới bất thường, process đáng ngờ, thay đổi trong config Nginx/PHP

Khả năng phục hồi nhanh thường quan trọng ngang khả năng phòng thủ.

Kết luận: bảo mật theo lớp là cách thực tế nhất cho web hosting

Để secure một Ubuntu server cho web hosting, không có “một lệnh thần kỳ” nào đủ cả. Điều hiệu quả là kết hợp nhiều lớp:

Ubuntu tối giản, cập nhật và khóa SSH
Nginx làm lớp chắn đầu tiên với HTTPS, header và rate limit
PHP bị cô lập, hạn chế hàm nguy hiểm và tài nguyên
MySQL chỉ mở đúng nơi, đúng user, đúng quyền
File permission, log và backup hỗ trợ phát hiện và phục hồi

Nếu phải ưu tiên theo thứ tự, hãy làm ngay 5 việc: tắt SSH password login, bật firewall tối thiểu, ép HTTPS, tách PHP-FPM pool theo site, và không public MySQL ra Internet. Chỉ riêng các bước này đã nâng mức an toàn của server lên đáng kể.

Bảo mật tốt không phải làm một lần rồi quên. Đó là một quy trình vận hành liên tục: cập nhật, kiểm tra, giám sát và cải tiến. Với web hosting, tư duy “nhiều lớp, ít quyền, dễ phục hồi” luôn là chiến lược bền vững nhất.

Chia sẻ:

Bài viết tương tự

Bình luận

Chưa có bình luận. Hãy là người đầu tiên!