Bảo Mật WordPress + OpenLiteSpeed: Firewall, Fail2Ban, Harden Từ A Đến Z

Câu trả lời nhanh

Bảo mật WordPress + OpenLiteSpeed toàn diện: cấu hình WAF chống SQL injection/XSS, Fail2Ban chặn brute force, harden file permissions, và 2FA cho wp-admin. Giảm 95% tấn công tự động sau khi áp dụng 12 bước trong hướng dẫn.

Mục lục Ẩn

Câu Hỏi Thường Gặp (FAQ)

Bảo mật WordPress trên OpenLiteSpeed cần những gì?

Combo tối thiểu gồm: Firewall (UFW/iptables + mod_security trên LiteSpeed), Fail2Ban chặn brute-force, harden wp-config.php và file permissions, SSL/HTTPS, backup tự động, và malware scanning định kỳ. Không cần làm hết một lần, nhưng nên triển khai theo thứ tự ưu tiên: Firewall > Fail2Ban > Harden WordPress > Harden OpenLiteSpeed > Backup > Monitoring.

OpenLiteSpeed có sẵn firewall không?

Có. OpenLiteSpeed tích hợp module mod_security tương thích规则 OWASP, có thể bật trực tiếp từ Admin Panel mà không cần cài thêm. Ngoài ra còn có Hotlink Protection, Access Control (IP whitelist/blacklist), và Rate Limiting built-in. Kết hợp với UFW/iptables ở OS level thì bạn có 2 lớp bảo vệ.

Fail2Ban hoạt động thế nào với WordPress?

Fail2Ban theo dõi log file (auth.log, access log), phát hiện các pattern brute-force như đăng nhập sai nhiều lần, rồi tự động chặn IP qua iptables/firewall. Bạn cần tạo custom filter cho wp-login.php, XML-RPC, và WordPress admin để Fail2Ban nhận diện được tấn công từ WordPress thay vì chỉ SSH.

Có nên dùng Wordfence hay Sucuri?

Theo trải nghiệm cá nhân, Wordfence free version là đủ cho hầu hết site WordPress. Nó cung cấp firewall application-level, malware scanner, và login security. Tuy nhiên nên dùng như lớp bổ sung, không thay thế cho server-level security (firewall, Fail2Ban). Sucuri mạnh hơn về malware cleanup nhưng bản trả phí khá đắt.

Backup bảo mật nên làm thế nào cho đúng?

Tối thiểu: backup database + files hàng ngày, giữ ít nhất 7 bản backup gần nhất, lưu ở server khác (offsite). Quan trọng nhất: test restore định kỳ. Backup không test restore thì giống như không backup. Tôi dùng script tự động chạy qua cron job, upload lên S3-compatible storage.

Tại Sao Bảo Mật WordPress Không Thể Bỏ Qua

Trong bài hướng dẫn cài đặt OpenLiteSpeed + WordPress, tôi đã đi qua phần setup cơ bản. Nhưng một server mới cài xong mà chưa harden thì giống như nhà có cửa nhưng chưa khóa — mời gọi mọi người bước vào.

WordPress chiếm hơn 43% website toàn cầu, và chính vì phổ biến nên nó là mục tiêu yêu thích của hacker. Theo thống kê từ Sucuri, khoảng 90% website bị hack trên các CMS đều là WordPress. Không phải vì WordPress yếu, mà vì phần lớn người dùng không cấu hình bảo mật đúng cách.

Khi bạn chạy WordPress trên OpenLiteSpeed, bạn có lợi thế: LiteSpeed có sẵn nhiều module bảo mật mà Nginx hay Apache cần cài thêm. Nhưng lợi thế chỉ trở thành bảo mật thực sự khi bạn biết cách bật và cấu hình chúng.

Bài viết này tổng hợp toàn bộ những gì tôi đã làm để bảo vệ server WordPress + OpenLiteSpeed của mình sau hơn 2 năm vận hành — từ firewall, Fail2Ban, harden WordPress/OpenLiteSpeed, đến backup strategy và monitoring. Mọi thứ đều đã test trên thực tế, không phải lý thuyết suông.

1. Firewall: Lớp Bảo Vệ Đầu Tiên

1.1 UFW — Uncomplicated Firewall

UFW là frontend của iptables, dễ dùng hơn nhiều so với viết raw iptables rules. Trên Ubuntu, UFW thường đã cài sẵn.

# Kiểm tra trạng thái
sudo ufw status verbose

# Default policy: chặn mọi incoming, cho phép mọi outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Cho phép SSH (QUAN TRỌNG: làm trước khi enable, nếu không bạn bị khóa khỏi server)
sudo ufw allow 22/tcp

# Cho phép HTTP và HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# OpenLiteSpeed Admin Panel (thay đổi port nếu bạn đã config khác)
# CHỈ cho phép từ IP của bạn, không mở cho tất cả
sudo ufw allow from YOUR_IP_ADDRESS to any port 7080

# Nếu dùng QUIC/HTTP3
sudo ufw allow 443/udp

# Enable firewall
sudo ufw enable

# Xác nhận
sudo ufw status numbered

Một sai lầm phổ biến là quên cho phép SSH trước khi enable UFW — kết quả là bạn mất kết nối vĩnh viễn với server. Luôn luôn allow 22/tcp trước khi ufw enable.

1.2 iptables Rules Chuyên Sâu Hơn

Nếu bạn cần control chi tiết hơn UFW, iptables cho phép viết rules phức tạp. Đây là bộ rules tôi dùng:

# Chặn ping (ICMP) — tùy chọn, giảm footprint
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# Chặn spoofing: không accept packet từ private IP đến interface public
sudo iptables -A INPUT -s 10.0.0.0/8 -j DROP
sudo iptables -A INPUT -s 172.16.0.0/12 -j DROP
sudo iptables -A INPUT -s 192.168.0.0/16 -j DROP

# SYN flood protection
sudo iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

# Giới hạn kết nối đồng thời từ 1 IP (80 connections max)
sudo iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 80 -j DROP

# Rate limiting: tối đa 20 kết nối mới/giây từ 1 IP
sudo iptables -A INPUT -p tcp --syn -m hashlimit \
  --hashlimit-upto 20/sec \
  --hashlimit-burst 20 \
  --hashlimit-mode srcip \
  --hashlimit-name syn_flood \
  -j ACCEPT

# Lưu rules (persist across reboot)
sudo apt install iptables-persistent
sudo netfilter-persistent save

1.3 OpenLiteSpeed Built-in Security

Đây là điểm mạnh của LiteSpeed so với Nginx. Trong Admin Panel (port 7080), bạn có:

Access Control (IP Restriction):

Vào Virtual Hosts > Context > /wp-admin/ hoặc tạo context mới:

URI: /wp-admin/
Location: /var/www/yoursite/public_html/wp-admin/
Access Allowed: YOUR_IP_ADDRESS,ANOTHER_IP
Access Denied: *

Điều này giới hạn wp-admin chỉ truy cập được từ IP của bạn. Rất hiệu quả chống brute-force admin login. Nhược điểm: nếu IP của bạn thay đổi (dùng ISP động, hoặc di chuyển), bạn phải cập nhật. Tôi giải quyết bằng VPN có static IP.

Hotlink Protection:

Vào Virtual Hosts > Security > Hotlink Protection:

Enable: Yes
Allowed Domains: thienlv.com www.thienlv.com
Redirect URL: /hotlink-denied.html

Chống hotlink tiết kiệm bandwidth, đặc biệt quan trọng nếu bạn có nhiều hình ảnh.

Rate Limiting:

Vào Virtual Hosts > General > Rate Limiting hoặc cấu hình ở server level:

Connection Level Throttling:
  Static: 200 requests/second
  Dynamic: 50 requests/second

Giới hạn rate giúp giảm tác động của DDoS nhẹ và bot spam.

1.4 mod_security Trên OpenLiteSpeed

mod_security là Web Application Firewall (WAF), phân tích HTTP requests và chặn những request độc hại dựa trên rules. OpenLiteSpeed hỗ trợ mod_security native.

Cài đặt OWASP ModSecurity Core Rule Set (CRS):

# Tạo thư mục rules
sudo mkdir -p /usr/local/lsws/conf/modsec
cd /usr/local/lsws/conf/modsec

# Download OWASP CRS
sudo git clone https://github.com/coreruleset/coreruleset.git
cd coreruleset

# Copy config mẫu
sudo cp crs-setup.conf.example crs-setup.conf

# Tạo file cấu hình chính
sudo tee /usr/local/lsws/conf/modsec/modsec.conf <<'EOF'
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecResponseBodyLimit 524288

SecAuditEngine RelevantOnly
SecAuditLog /var/log/lsws/modsec_audit.log
SecAuditLogParts ABFHK

SecDebugLog /var/log/lsws/modsec_debug.log
SecDebugLogLevel 0

# Include OWASP CRS rules
include /usr/local/lsws/conf/modsec/coreruleset/crs-setup.conf
include /usr/local/lsws/conf/modsec/coreruleset/rules/*.conf
EOF

Kích hoạt trong OpenLiteSpeed Admin Panel:

Vào Server > General > Modules, thêm module:

Module: mod_security
Enable: Yes

Sau đó restart LiteSpeed:

sudo systemctl restart lsws

Lưu ý quan trọng: OWASP CRS default rules khá aggressive, có thể block legitimate requests. Tôi khuyến nghị:

  • Bắt đầu với SecRuleEngine DetectionOnly (chỉ ghi log, không chặn) trong 1-2 tuần
  • Review log /var/log/lsws/modsec_audit.log để xem false positives
  • Thêm exclusion rules cho WordPress (REST API, wp-admin AJAX)
  • Sau đó chuyển sang On

Thêm exclusion cơ bản cho WordPress:

# Thêm vào cuối modsec.conf, trước include rules
SecRule REQUEST_URI "@beginsWith /wp-admin/admin-ajax.php" "id:1000,phase:1,pass,nolog,ctl:ruleRemoveById=941100-942999"
SecRule REQUEST_URI "@beginsWith /wp-json/" "id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=941100-942999"

2. Fail2Ban: Chặn Brute-Force Tự Động

Fail2Ban là tool bảo mật tôi coi là bắt buộc phải có trên mọi server. Nó scan log files, phát hiện dấu hiệu tấn công (đăng nhập sai nhiều lần, scan vulnerability, spam), rồi tự động update firewall rules để chặn IP độc hại.

2.1 Cài Đặt Fail2Ban

sudo apt update
sudo apt install fail2ban -y

# Tạo local config (không sửa file mặc định, upgrade sẽ mất)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

2.2 Cấu Hình SSH Protection

Tạo hoặc chỉnh sửa /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
action = iptables-multiport[name=sshd, port="22", protocol=tcp]

Giải thích: nếu 1 IP đăng nhập SSH sai 3 lần trong 10 phút (600 giây), chặn IP đó trong 1 giờ (3600 giây).

Nếu bạn dùng SSH key và disable password login rồi (nên làm), đây là lớp bảo vệ thêm. Nếu vẫn dùng password SSH thì đây thực sự là must-have.

2.3 Cấu Hình WordPress Login Protection

Fail2Ban mặc định không biết đọc WordPress log. Ta cần tạo custom filter.

Bước 1: Cài plugin WordPress ghi log đăng nhập

Cài plugin “WP fail2ban” hoặc thêm code sau vào wp-config.php để WordPress ghi log đăng nhập vào syslog:

// Thêm vào wp-config.php, trên dòng "/* That's all, stop editing! */"
// WordPress authentication logging for Fail2Ban
function custom_login_log($user_login, $user) {
    error_log("WordPress authentication success for $user_login from $_SERVER[REMOTE_ADDR]");
}
add_action('wp_login', 'custom_login_log', 10, 2);

function custom_login_failed_log($username) {
    error_log("WordPress authentication failure for $username from $_SERVER[REMOTE_ADDR]");
}
add_action('wp_login_failed', 'custom_login_failed_log');

Hoặc đơn giản hơn, dùng plugin WP fail2ban Redux — nó tự ghi log vào syslog chuẩn Fail2Ban format.

sudo -u www-data wp plugin install wp-fail2ban-redux --activate --path=/var/www/thienlv.com/public_html

Bước 2: Tạo Fail2Ban filter cho WordPress

Tạo file /etc/fail2ban/filter.d/wordpress.conf:

[Definition]
failregex = .*WordPress authentication failure.*from <HOST>$
            .*POST /wp-login.php.*HTTP/1\..* 200 .*from <HOST>$
            .*POST /xmlrpc.php.*HTTP/1\..* 200 .*from <HOST>$
ignoreregex =

Bước 3: Tạo filter cho XML-RPC

Tạo file /etc/fail2ban/filter.d/wordpress-xmlrpc.conf:

[Definition]
failregex = .*POST /xmlrpc.php.*from <HOST>$
ignoreregex =

Bước 4: Thêm jails vào jail.local

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/syslog
maxretry = 5
findtime = 600
bantime = 7200
action = iptables-multiport[name=wordpress, port="80,443", protocol=tcp]

[wordpress-xmlrpc]
enabled = true
port = http,https
filter = wordpress-xmlrpc
logpath = /var/log/syslog
maxretry = 2
findtime = 3600
bantime = 86400
action = iptables-multiport[name=xmlrpc, port="80,443", protocol=tcp]

Chú ý: XML-RPC tôi set rất strict — chỉ 2 lần retry trong 1 giờ, ban 24 giờ. Vì bình thường几乎没有 legitimate traffic nào đến xmlrpc.php ngoài tấn công.

Bước 5: Restart Fail2Ban

sudo systemctl restart fail2ban

# Kiểm tra jails đang chạy
sudo fail2ban-client status

# Kiểm tra chi tiết jail wordpress
sudo fail2ban-client status wordpress

# Xem log
sudo tail -f /var/log/fail2ban.log

2.4 Kiểm Tra Fail2Ban Hoạt Động

# Xem tất cả IP đang bị ban
sudo fail2ban-client banned

# Unban 1 IP cụ thể
sudo fail2ban-client set wordpress unbanip 1.2.3.4

# Test filter với log mẫu
sudo fail2ban-regex /var/log/syslog /etc/fail2ban/filter.d/wordpress.conf

Sau khi cấu hình xong, thử đăng nhập sai 5 lần — bạn sẽ thấy IP bị ban trong log. Rất hài lòng khi thấy nó hoạt động.

3. Harden WordPress

3.1 File Permissions

File permissions sai là một trong những nguyên nhân phổ biến nhất dẫn đến bị hack. Đây là bộ permissions tôi áp dụng:

# Ownership: www-data cho web server
sudo find /var/www/thienlv.com/public_html -type f -exec chmod 644 {} \;
sudo find /var/www/thienlv.com/public_html -type d -exec chmod 755 {} \;

# wp-config.php chỉ cho owner đọc (QUAN TRỌNG)
sudo chmod 440 /var/www/thienlv.com/public_html/wp-config.php

# wp-content/uploads writable cho upload
sudo chmod 775 /var/www/thienlv.com/public_html/wp-content/uploads

# Deny access to wp-config.php qua .htaccess (LiteSpeed hỗ trợ)
# Thêm vào .htaccess:
<files wp-config.php>
    order allow,deny
    deny from all
</files>

# Deny access to .htaccess itself
<files .htaccess>
    order allow,deny
    deny from all
</files>

# Disable directory listing
# Thêm vào .htaccess:
Options -Indexes

# Deny access to sensitive files
<files xmlrpc.php>
    order allow,deny
    deny from all
</files>

# Block access to wp-includes
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^wp-admin/includes/ - [F,L]
    RewriteRule !^wp-includes/ - [S=3]
    RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
    RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
    RewriteRule ^wp-includes/Theme\.php$ - [F,L]
</IfModule>

3.2 wp-config.php Security

Thay Security Keys:

Vào api.wordpress.org/secret-key/1.1/salt/ để generate bộ keys mới, thay thế đoạn cũ trong wp-config.php:

define('AUTH_KEY',         'thay bằng key mới');
define('SECURE_AUTH_KEY',  'thay bằng key mới');
define('LOGGED_IN_KEY',    'thay bằng key mới');
define('NONCE_KEY',        'thay bằng key mới');
define('AUTH_SALT',        'thay bằng key mới');
define('SECURE_AUTH_SALT', 'thay bằng key mới');
define('LOGGED_IN_SALT',   'thay bằng key mới');
define('NONCE_SALT',       'thay bằng key mới');

Nên thay security keys mỗi 6-12 tháng, hoặc ngay khi nghi ngờ bị compromise. Thay keys sẽ invalidate tất cả session hiện tại.

Disable File Editor:

// Thêm vào wp-config.php
define('DISALLOW_FILE_EDIT', true);  // Vô hiệu hóa theme/plugin editor trong admin
define('DISALLOW_FILE_MODS', true);  // Vô hiệu hóa cài/sửa plugin/theme từ admin
define('WP_AUTO_UPDATE_CORE', true); // Tự động update core
define('FORCE_SSL_ADMIN', true);     // Bắt buộc HTTPS cho admin

DISALLOW_FILE_MODS cũng ẩn notifications cài plugin mới trong admin. Nếu bạn cần cài plugin, tắt tạm, cài xong bật lại. Phiền một chút nhưng an toàn hơn nhiều.

Di chuyển wp-config.php lên thư mục cao hơn:

WordPress tự động tìm wp-config.php ở thư mục cao hơn document root nếu không tìm thấy trong thư mục hiện tại. Di chuyển lên 1 level:

mv /var/www/thienlv.com/public_html/wp-config.php /var/www/thienlv.com/wp-config.php

Nhờ đó,wp-config.php nằm ngoài document root, web server không thể phục vụ file này kể cả khi cấu hình sai.

3.3 Giới Hạn Đăng Nhập

Dùng plugin thay vì code tay. Tôi dùng Limit Login Attempts Reloaded:

sudo -u www-data wp plugin install limit-login-attempts-reloaded --activate --path=/var/www/thienlv.com/public_html

Cấu hình: 4 lần thử trong 20 phút, lockout 24 giờ, notify email khi có lockout. Kết hợp với Fail2Ban thì bạn có 2 lớp bảo vệ login: application-level (plugin) + server-level (Fail2Ban).

3.4 Two-Factor Authentication (2FA)

Bắt buộc nên bật 2FA cho admin account. Tôi dùng Wordfence Login Security (tách riêng từ Wordfence, nhẹ hơn):

sudo -u www-data wp plugin install wordfence-login-security --activate --path=/var/www/thienlv.com/public_html

Hoặc nếu đã cài Wordfence đầy đủ thì dùng 2FA built-in. Quét QR code bằng Google Authenticator hoặc Authy, xong.

Theo tôi, 2FA là biện pháp đơn giản nhưng hiệu quả nhất chống chiếm tài khoản admin. Dù password bị lộ, hacker vẫn không đăng nhập được nếu không có mã 2FA.

3.5 Vô Hiệu Hoá XML-RPC

XML-RPC là cổng vào phổ biến cho brute-force attacks và DDoS. Nếu bạn không dùng WordPress app mobile hay pingback/trackback, hãy vô hiệu hóa hoàn toàn:

# Thêm vào .htaccess
<Files xmlrpc.php>
    Order Allow,Deny
    Deny from all
</Files>

Hoặc nếu cần giữ lại cho một số plugin (như Jetpack), cho phép chỉ IP của Jetpack:

<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
    Allow from jetpack.wordpress.com
</Files>

3.6 Xóa Default Content

# XóaHello World post, sample page, default comment
sudo -u www-data wp post delete 1 --force --path=/var/www/thienlv.com/public_html
sudo -u www-data wp post delete 2 --force --path=/var/www/thienlv.com/public_html
sudo -u www-data wp comment delete 1 --force --path=/var/www/thienlv.com/public_html

# Xóa unused themes
sudo -u www-data wp theme delete twentytwentyfive --path=/var/www/thienlv.com/public_html
sudo -u www-data wp theme delete twentytwentyfour --path=/var/www/thienlv.com/public_html

# XóaHello WorldPlugin (Akismet, Hello Dolly nếu không dùng)
sudo -u www-data wp plugin delete akismet --path=/var/www/thienlv.com/public_html
sudo -u www-data wp plugin delete hello --path=/var/www/thienlv.com/public_html

Mỗi theme/plugin không dùng là một attack surface tiềm năng. Xóa hết những gì không cần.

4. Harden OpenLiteSpeed

4.1 Ẩn Version Header

Mặc định OpenLiteSpeed hiển thị version trong HTTP header, giúp attacker biết chính xác version bạn đang chạy để tìm exploit.

Vào Server > General > Server Signature: chọn Hide hoặc Off. Restart LiteSpeed.

Kiểm tra:

curl -I https://thienlv.com | grep Server

Header chỉ nên hiện “LiteSpeed” hoặc “lsquic” chứ không kèm version number.

4.2 Restrict Admin Panel Access

OpenLiteSpeed Admin Panel chạy trên port 7080 (mặc định). Đây là mục tiêu tấn công phổ biến.

Thay đổi port mặc định:

Vào Server > General > Admin Port: đổi sang port ngẫu nhiên, ví dụ 58034.

Giới hạn IP truy cập:

Đã làm ở phần UFW: chỉ cho phép IP của bạn truy cập admin port. Thêm lớp nữa, trong Admin Panel:

Vào Server > General > Access Control: thêm IP được phép.

Bật SSL cho Admin Panel:

Nếu đã có SSL (xem bài SSL/HTTPS với Let’s Encrypt trên OpenLiteSpeed), cấu hình Admin Panel dùng HTTPS:

Vào Server > Admin Listeners > adminSSL: trỏ đến SSL certificate của bạn.

4.3 Anti-Hotlink Protection

Như đã đề cập ở phần 1.3, bật Hotlink Protection trong Admin Panel. Ngoài ra, có thể thêm rule trong .htaccess:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?thienlv\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?bing\. [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|svg|mp4)$ - [F,NC]

Cho phép Google/Bing referer vì search engine image search cần hiển thị thumbnail.

4.4 Anti-DDoS Cơ Bản

OpenLiteSpeed có built-in chống DDoS nhẹ, nhưng không thay thế được dedicated DDoS protection (Cloudflare, etc.).

Connection/Throttle Limiting:

Vào Server > Tuning > Connection throttling:

Max Connections: 1000
Connection Soft Limit: 800
Connection Hard Limit: 1000
Grace Period (sec): 10
Ban Period (sec): 60

Nghĩa là nếu 1 IP mở quá 800 kết nối đồng thời trong 10 giây, ban 60 giây.

Request Throttling:

Vào Virtual Hosts > Security > Request Throttling:

Dynamic Request Limit: 40/sec
Static Request Limit: 200/sec

Đối với DDoS規模 lớn, bạn cần Cloudflare hoặc CDN có DDoS protection. LiteSpeed chỉ xử lý được mức nhẹ-trung bình. May mắn là hầu hết blog nhỏ không bị DDoS targeted.

5. Malware Scanning

5.1 ClamAV — Server-Level Scanner

ClamAV là antivirus open-source, chạy được trên Linux:

# Cài đặt
sudo apt install clamav clamav-daemon -y

# Update virus database
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam

# Scan toàn bộ WordPress directory
sudo clamscan -r -i /var/www/thienlv.com/public_html --log=/var/log/clamav/scan.log

# Scan và xóa file nhiễm
sudo clamscan -r -i /var/www/thienlv.com/public_html --remove

Tạo cron job scan hàng tuần:

# Thêm vào crontab
sudo crontab -e

# Scan lúc 3 giờ sáng Chủ Nhật hàng tuần
0 3 * * 0 clamscan -r -i /var/www/thienlv.com/public_html --log=/var/log/clamav/scan-$(date +\%Y\%m\%d).log

ClamAV chạy khá chậm (full scan có thể mất 30+ phút), nên chỉ nên chạy định kỳ, không phải realtime. Đối với WordPress, scanner application-level như Wordfence hiệu quả hơn trong việc phát hiện PHP malware.

5.2 Wordfence — WordPress Security Plugin

sudo -u www-data wp plugin install wordfence --activate --path=/var/www/thienlv.com/public_html

Wordfence miễn phí cung cấp:

  • Firewall: chặn malicious requests dựa trên signature database
  • Malware Scanner: scan core files, themes, plugins so sánh với repository chính thức
  • Login Security: 2FA, CAPTCHA, limit login attempts
  • Threat Intelligence: cảnh báo khi plugin/theme có vulnerability mới phát hiện

Cấu hình quan trọng sau khi cài:

  • Bật Extended Protection (Wordfence > All Options > Firewall)
  • Chạy scan đầu tiên: Wordfence > Scan > Start New Scan
  • Bật email alerts cho critical issues
  • Set scheduled scan: hàng ngày vào lúc low-traffic (2-3 AM)

Nhược điểm Wordfence: khá nặng, có thể ảnh hưởng performance trên VPS nhỏ (1GB RAM). Nếu server của bạn yếu, cân nhắc dùng LiteSpeed Cache + chỉ bật Wordfence scan khi cần, tắt firewall application-level (đã có mod_security ở server level rồi).

6. Security Headers

Security headers là HTTP response headers hướng dẫn browser cách xử lý nội dung trang web. Dù không ảnh hưởng trực tiếp đến server, chúng bảo vệ người dùng khỏi XSS, clickjacking, và các client-side attacks.

Trên OpenLiteSpeed, thêm headers trong .htaccess hoặc cấu hình Virtual Host:

# Thêm vào .htaccess hoặc Virtual Host context

# Ngăn nhúng trang vào iframe (clickjacking protection)
Header always set X-Frame-Options "SAMEORIGIN"

# Ngăn browser đoán MIME type (MIME sniffing protection)
Header always set X-Content-Type-Options "nosniff"

# Bật browser XSS protection (cũ nhưng vẫn nên có)
Header always set X-XSS-Protection "1; mode=block"

# Kiểm soát referrer information
Header always set Referrer-Policy "strict-origin-when-cross-origin"

# Content Security Policy (tùy chỉnh theo site)
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https:; frame-ancestors 'self';"

# Permissions Policy (trước đây là Feature-Policy)
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"

# HSTS (chỉ bật khi đã chắc chắn HTTPS hoạt động ổn định)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Lưu ý về HSTS: một khi bật HSTS, browser sẽ chỉ truy cập site qua HTTPS. Nếu SSL có vấn đề, người dùng không thể truy cập site. Bắt đầu với max-age=300 (5 phút) để test, sau đó tăng dần lên 1 năm.

Kiểm tra security headers:

curl -I https://thienlv.com | grep -i "x-frame\|x-content\|strict-transport\|content-security\|referrer-policy"

Hoặc dùng securityheaders.com để test và chấm điểm. Mục tiêu: đạt grade A hoặc A+.

7. Backup Strategy

Backup là biện pháp bảo mật cuối cùng nhưng quan trọng nhất. Khi mọi thứ khác thất bại, backup cứu bạn.

Nguyên tắc backup của tôi: 3-2-1 — 3 bản sao, 2 loại storage khác nhau, 1 bản offsite.

7.1 Script Backup Tự Động

Tạo file /root/backup-wordpress.sh:

#!/bin/bash
# WordPress Backup Script for thienlv.com
# Chạy bởi cron hàng ngày lúc 2 AM

SITE_NAME="thienlv.com"
SITE_PATH="/var/www/${SITE_NAME}/public_html"
BACKUP_DIR="/backup/${SITE_NAME}"
DATE=$(date +%Y-%m-%d_%H%M)
KEEP_DAYS=7

# Database credentials từ wp-config.php
DB_NAME=$(grep "DB_NAME" ${SITE_PATH}/wp-config.php | cut -d "'" -f 4)
DB_USER=$(grep "DB_USER" ${SITE_PATH}/wp-config.php | cut -d "'" -f 4)
DB_PASS=$(grep "DB_PASSWORD" ${SITE_PATH}/wp-config.php | cut -d "'" -f 4)

# Tạo thư mục backup
mkdir -p ${BACKUP_DIR}

# Backup database
mysqldump -u${DB_USER} -p${DB_PASS} ${DB_NAME} | gzip > ${BACKUP_DIR}/db_${DATE}.sql.gz

# Backup files
tar -czf ${BACKUP_DIR}/files_${DATE}.tar.gz -C /var/www/${SITE_NAME} public_html

# Xóa backup cũ hơn KEEP_DAYS
find ${BACKUP_DIR} -name "*.gz" -mtime +${KEEP_DAYS} -delete
find ${BACKUP_DIR} -name "*.tar.gz" -mtime +${KEEP_DAYS} -delete

# Upload lên remote storage (ví dụ: S3-compatible)
# Cần cài awscli: sudo apt install awscli
# aws s3 sync ${BACKUP_DIR}/ s3://your-bucket/${SITE_NAME}/ --delete

echo "[$DATE] Backup completed: db_${DATE}.sql.gz, files_${DATE}.tar.gz" >> /var/log/wordpress-backup.log
# Phân quyền
sudo chmod +x /root/backup-wordpress.sh

# Tạo thư mục backup
sudo mkdir -p /backup/thienlv.com

# Thêm cron job
sudo crontab -e
# Thêm dòng:
0 2 * * * /root/backup-wordpress.sh

7.2 Test Restore

BACKUP MÀ KHÔNG TEST RESTORE THÌ GIỐNG NHƯ KHÔNG BACKUP. Tôi nhấn mạnh vì bản thân từng rơi vào tình huống cần restore thì phát hiện backup bị lỗi.

# Test restore database
gunzip < /backup/thienlv.com/db_2026-05-26_0200.sql.gz | mysql -uDB_USER -pDB_PASS DB_NAME

# Test restore files
tar -xzf /backup/thienlv.com/files_2026-05-26_0200.tar.gz -C /tmp/test-restore/

Kiểm tra test restore hàng tháng. Đảm bảo process restore được documented rõ ràng để khi cần làm thật, bạn không phải guess.

8. Monitoring Và Phát Hiện Xâm Nhập

8.1 Log Analysis

Log là tài sản vô giá khi điều tra sự cố bảo mật. Các log quan trọng cần theo dõi:

# OpenLiteSpeed access log
tail -f /var/log/lsws/thienlv.com/access.log

# OpenLiteSpeed error log
tail -f /var/log/lsws/thienlv.com/error.log

# ModSecurity audit log
tail -f /var/log/lsws/modsec_audit.log

# Fail2Ban log
tail -f /var/log/fail2ban.log

# SSH auth log
tail -f /var/log/auth.log

# Syslog (WordPress login attempts)
tail -f /var/log/syslog | grep WordPress

Thay vì tail thủ công, tôi dùng script đơn giản phân tích log hàng ngày:

#!/bin/bash
# /root/daily-security-report.sh
# Chạy hàng ngày qua cron

DATE=$(date -d "yesterday" +%Y-%m-%d)
REPORT="/tmp/security-report-${DATE}.txt"

echo "=== SECURITY REPORT for ${DATE} ===" > ${REPORT}
echo "" >> ${REPORT}

echo "--- Fail2Ban Bans ---" >> ${REPORT}
grep "Ban " /var/log/fail2ban.log | grep "${DATE}" | awk '{print $NF}' | sort | uniq -c | sort -rn | head -20 >> ${REPORT}

echo "" >> ${REPORT}
echo "--- Top 20 IPs by requests ---" >> ${REPORT}
awk -v d="${DATE}" '$0 ~ d {print $1}' /var/log/lsws/thienlv.com/access.log | sort | uniq -c | sort -rn | head -20 >> ${REPORT}

echo "" >> ${REPORT}
echo "--- WordPress login failures ---" >> ${REPORT}
grep "authentication failure" /var/log/syslog | grep "${DATE}" >> ${REPORT}

echo "" >> ${REPORT}
echo "--- ModSecurity blocks ---" >> ${REPORT}
grep "${DATE}" /var/log/lsws/modsec_audit.log 2>/dev/null | tail -50 >> ${REPORT}

# Gửi report qua email hoặc Telegram
cat ${REPORT}

8.2 Intrusion Detection với AIDE

AIDE (Advanced Intrusion Detection Environment) theo dõi sự thay đổi của files. Nếu hacker chỉnh sửa core files, AIDE sẽ cảnh báo:

# Cài đặt
sudo apt install aide -y

# Khởi tạo database
sudo aideinit

# Đặt database vào đúng vị trí
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Kiểm tra changes (chạy hàng ngày)
sudo aide --check

# Update database sau khi thay đổi files hợp lệ
sudo aide --update
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

Tạo cron job kiểm tra hàng ngày:

# /etc/cron.daily/aide-check
#!/bin/bash
/usr/bin/aide --check | mail -s "AIDE Daily Check - $(hostname)" admin@thienlv.com

9. Troubleshooting Thường Gặp

Fail2Ban không chặn IP

# Kiểm tra filter có match log không
sudo fail2ban-regex /var/log/syslog /etc/fail2ban/filter.d/wordpress.conf

# Nếu không match, kiểm tra log format
tail -20 /var/log/syslog | grep WordPress

# Kiểm tra Fail2Ban đang chạy không
sudo systemctl status fail2ban

# Xem chi tiết lỗi
sudo fail2ban-client -vvv status wordpress

Nguyên nhân phổ biến nhất: log format trong filter không khớp với log format thực tế. Chỉnh regex trong filter cho phù hợp.

mod_security chặn legitimate requests

# Tìm rule nào đang gây false positive
grep "id \"" /var/log/lsws/modsec_audit.log | tail -20

# Disable rule cụ thể (thêm vào modsec.conf)
SecRuleRemoveById 941100
# Hoặc cho path cụ thể
SecRule REQUEST_URI "@beginsWith /wp-admin/admin-ajax.php" "id:1002,phase:1,pass,nolog,ctl:ruleRemoveById=941100"

Quên mật khẩu admin WordPress

# Reset password qua WP-CLI
sudo -u www-data wp user update admin --user_pass="new_password" --path=/var/www/thienlv.com/public_html

Không truy cập được wp-admin sau khi restrict IP

# Kiểm tra IP hiện tại của bạn
curl ifconfig.me

# Thêm IP mới vào UFW
sudo ufw allow from YOUR_NEW_IP to any port 7080

# Hoặc xóa restriction tạm thời
sudo ufw delete allow from OLD_IP to any port 7080

SSL certificate hết hạn

# Check expiry
sudo certbot certificates

# Force renew
sudo certbot renew --force-renewal

# Restart OpenLiteSpeed
sudo systemctl restart lsws

Chi tiết hơn về SSL troubleshooting, xem bài hướng dẫn SSL/HTTPS với Let’s Encrypt trên OpenLiteSpeed.

10. Checklist Tổng Hợp

Để dễ theo dõi, đây là checklist tôi dùng khi setup bảo mật cho server mới:

Layer Hành động Ưu tiên
Network UFW: chỉ mở 22, 80, 443, admin port Critical
Network SSH key-only, disable password auth Critical
Firewall Fail2Ban cho SSH, wp-login, XML-RPC Critical
Firewall mod_security với OWASP CRS High
WordPress wp-config.php: security keys, disable editor Critical
WordPress File permissions đúng (644/755) Critical
WordPress 2FA cho admin Critical
WordPress Disable XML-RPC (nếu không dùng) High
WordPress Limit login attempts High
WordPress Xóa unused themes/plugins Medium
LiteSpeed Ẩn version header Medium
LiteSpeed Restrict admin panel (IP + đổi port) High
LiteSpeed Anti-hotlink, rate limiting Medium
SSL Let’s Encrypt + HSTS + TLS 1.3 Critical
Headers X-Frame-Options, CSP, HSTS High
Backup Tự động daily + offsite + test restore Critical
Monitoring Log analysis + AIDE High
Scanning Wordfence scan hàng ngày High

Ý Kiến Cá Nhân Sau 2 Năm Vận Hành

Sau hơn 2 năm chạy WordPress trên OpenLiteSpeed, đây là vài nhận xét thực tế:

OpenLiteSpeed thực sự an toàn hơn Nginx/Apache — không phải vì code tốt hơn, mà vì ít người dùng hơn nên ít attacker nhắm vào. Combined với built-in mod_security support và .htaccess compatibility, bạn có lợi thế bảo mật mà không cần cấu hình phức tạp.

Fail2Ban là MVP bảo mật. Trong tháng đầu tiên vận hành, Fail2Ban đã chặn hơn 200 IP brute-force. Không có nó, server đã bị brute-force liên tục. Cài đặt mất 30 phút, bảo vệ 24/7.

mod_security tốn công nhưng đáng giá. Giai đoạn đầu tốn 2 tuần tinh chỉnh rules, thêm exclusion cho WordPress REST API và AJAX. Nhưng sau khi ổn định, nó chặn sạch SQL injection, XSS, và file injection attempts. Xem log mod_security thỉnh thoảng khá thú vị — bạn sẽ thấy attacker cố gắng những gì.

Wordfence free là đủ cho blog nhỏ. Tôi từng cân nhắc bản premium nhưng nhận ra free version đã cover đủ: malware scan, vulnerability alerts, 2FA. Premium thêm realtime threat intelligence và country blocking, nhưng với blog traffic nhỏ thì không cần thiết.

Backup là thứ bạn không bao giờ nghĩ đến cho đến khi cần. Tôi từng mất 1 ngày content vì thử plugin mới gây lỗi database. May mà có backup 24 giờ trước. Từ đó, backup tự động hàng ngày, test restore hàng tháng, không ngoại lệ.

Security là quá trình, không phải sản phẩm. Không có “setup xong là an toàn”. Mỗi tháng có WordPress core update, plugin updates, vulnerability mới phát hiện. Duy trì thói quen: update hàng tuần, check log hàng ngày (qua script), review Fail2Ban ban list, chạy malware scan. Mất 15-30 phút/tuần nhưng giúp bạn yên tâm.

Nếu bạn vừa mới bắt đầu, hãy làm theo thứ tự ưu tiên trong checklist: UFW + SSH key > Fail2Ban > wp-config.php harden > SSL + security headers > backup > monitoring. Làm từng bước, test từng bước, không rush. Bảo mật tốt là bảo mật bạn hiểu rõ, không phải bảo mật copy-paste rồi quên.

Thanh Tùng

Mình là Thanh Tùng. Bạn bè gọi mình là "bác sĩ máy tính" vì hễ máy nào có vấn đề là mình muốn mò vào xem sao. Mình viết hướng dẫn theo cách mà mình mong người khác đã viết cho mình ngày xưa — từng bước rõ ràng, không bỏ sót, và nói luôn cái gì hay bị lỗi. Ngoài giờ làm mình chơi guitar, nuôi mèo, và có một con VPS riêng dành riêng cho việc cài thử đủ thứ linh tinh.

Xem tất cả bài viết →

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *