2 giờ sáng, Telegram réo lên. Client nhắn: “Website mình bị Google đánh dấu là nguy hiểm rồi anh ơi”. Mình SSH vào server, chạy ls -la /var/www/html — thấy ngay một đống file .php lạ xuất hiện từ hôm qua. Webshell. Ai đó đã upload và đang dùng server như một botnet node.
Sau vụ đó, mình setup LMD + ClamAV trên tất cả web server. Giờ chia sẻ lại quy trình — từ cài nhanh 5 phút đến cấu hình tự động hoàn chỉnh.
Quick Start — Chạy ngay trong 5 phút
Nếu server đang bị nghi ngờ nhiễm mã độc và cần quét ngay, làm theo thứ tự này:
# 1. Cài ClamAV trước (database lớn, tải lâu)
sudo apt update && sudo apt install -y clamav clamav-daemon
# 2. Cập nhật virus database (quan trọng!)
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam
# 3. Tải và cài LMD
cd /tmp
wget https://www.rfxn.com/downloads/maldetect-current.tar.gz
tar -zxvf maldetect-current.tar.gz
cd maldetect-*/
sudo ./install.sh
# 4. Quét thư mục web ngay lập tức
sudo maldet -a /var/www/html
Xong. LMD sẽ quét và in report ra màn hình. Nếu thấy kết quả có dòng hits: X với X > 0, tiếp tục đọc phần bên dưới để xử lý.
Hiểu LMD và ClamAV làm gì khác nhau
Nhiều người cài một trong hai rồi nghĩ là đủ — thực ra chúng bổ sung cho nhau.
ClamAV là antivirus engine với database hàng triệu signature, giỏi phát hiện virus, trojan, và malware phổ thông. Nhưng ClamAV không được tối ưu cho web shell — loại mã độc phổ biến nhất trên web server.
Linux Malware Detect (LMD) được xây dựng đặc biệt cho shared hosting và web server. Signature của LMD được tổng hợp từ các vụ tấn công thực tế vào hosting environment — webshell, PHP backdoor, mã obfuscate — những thứ ClamAV hay bỏ sót.
Khi dùng chung: LMD dùng ClamAV làm scanning engine (nhanh hơn) đồng thời vẫn dùng signature riêng của mình. Hai lớp phát hiện, một lần quét.
Cấu hình LMD đúng cách
File config chính nằm ở /usr/local/maldetect/conf.maldet. Mình sẽ chỉ các option quan trọng cần thay đổi so với mặc định:
sudo nano /usr/local/maldetect/conf.maldet
# Bật email alert (thay bằng email thật)
email_alert="1"
email_addr="[email protected]"
# Bật quarantine tự động — file độc bị cách ly, không xóa
quar_hits="1"
quar_clean="1" # Cố gắng clean trước khi quarantine
quar_susp="0" # Không quarantine file "nghi ngờ" tự động (hay false positive)
# Dùng ClamAV làm engine (nhanh hơn nhiều)
clamav_scan="1"
# Scan real-time với inotify (cần kernel support)
inotify_base="/var/www"
inotify_users="www-data"
# Giới hạn scan để không ngốn CPU
scan_max_filesize="2048" # Bỏ qua file > 2MB
scan_tmpdir_paths="/tmp /var/tmp /dev/shm" # Luôn scan thư mục tmp
Sau khi sửa, restart service:
sudo systemctl restart maldet
Cấu hình quét tự động hàng ngày
LMD cài xong đã tạo sẵn cron job tại /etc/cron.daily/maldet, nhưng mặc định nó quét /tmp và /var/tmp. Thêm thư mục web vào:
sudo nano /etc/cron.daily/maldet
Tìm dòng có maldet và thêm path web:
#!/bin/bash
/usr/local/maldetect/maldet -b -r /var/www/ 2>&1 | logger -t maldet
Flag -b chạy background, -r là recursive scan. Kết quả được ghi vào syslog.
Nếu muốn nhận report qua email mỗi tuần thay vì mỗi ngày (để tránh spam inbox), tạo cron riêng:
sudo crontab -e
# Quét sâu lúc 3 giờ sáng mỗi Chủ nhật
0 3 * * 0 /usr/local/maldetect/maldet -a /var/www/ && /usr/local/maldetect/maldet --report REPORT_DATE
Xử lý khi phát hiện malware
Chạy xong thấy có hits, đây là các lệnh cần biết:
# Xem report gần nhất
maldet --report
# Xem chi tiết một report cụ thể (YYYYMMDD-HHMMSS)
maldet --report 20240618-030000
# Xem danh sách file bị quarantine
ls -la /usr/local/maldetect/quarantine/
# Restore file nếu false positive
maldet -s /usr/local/maldetect/quarantine/FILENAME
# Clean (cố gắng xóa mã độc khỏi file, giữ file)
maldet -c /path/to/file.php
Thực tế mình hay dùng -c cho file cần giữ (như plugin WordPress bị inject), còn webshell rõ ràng thì xóa thẳng sau khi quarantine.
Nâng cao: Scan real-time với inotify
Thay vì đợi cron chạy, LMD có thể theo dõi filesystem real-time và quét ngay khi có file mới được tạo/sửa:
# Kiểm tra kernel có hỗ trợ inotify không
ls /proc/sys/fs/inotify/
# Nếu thấy max_queued_events, max_user_instances, max_user_watches là OK
# Tăng giới hạn inotify nếu cần (web server nhiều file)
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Start monitor real-time
sudo maldet -m /var/www/
# Kiểm tra monitor đang chạy
sudo maldet --monitor-status
Lưu ý: monitor real-time tốn khoảng 50-100MB RAM tùy số file đang theo dõi. Trên VPS nhỏ (1GB RAM), cân nhắc chỉ monitor thư mục upload thay vì toàn bộ web root.
Kết hợp với ClamAV daemon để scan nhanh hơn
Mặc định ClamAV load toàn bộ signature vào RAM mỗi lần scan — chậm. Dùng clamdscan với daemon thường trú thay vì clamscan:
# Bật clamav-daemon
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Kiểm tra daemon đang chạy
sudo systemctl status clamav-daemon
# Test scan với daemon (nhanh hơn clamscan nhiều lần)
clamdscan /var/www/html/suspicious-file.php
Trong config LMD (conf.maldet), đặt clamav_scan="1" — LMD sẽ tự dùng clamdscan khi daemon available.
Tips thực tế từ production
Đặt mật khẩu mạnh ngay từ đầu. Phần lớn webshell vào được vì brute force FTP/SSH, hoặc password WordPress bị đoán. Mình dùng password generator tại toolcraft.app/vi/tools/security/password-generator để tạo mật khẩu 32 ký tự cho mọi account trên server — tool chạy hoàn toàn trên trình duyệt, không gửi gì lên server nên không lo bị intercept.
Scan trước khi restore backup. Nếu server bị hack và bạn restore từ backup cũ, chạy LMD quét backup trước — đôi khi malware đã nằm trong backup từ trước khi bị phát hiện.
Whitelist false positive. LMD hay flag một số file legitimate (như Adminer, một số WordPress plugin). Thêm vào whitelist thay vì disable scan:
# Whitelist theo file hash
maldet -w /var/www/html/adminer.php
# Xem danh sách whitelist
cat /usr/local/maldetect/ignore/hex
cat /usr/local/maldetect/ignore/paths
Giữ signature update tự động. LMD tự update signature khi chạy, nhưng ClamAV cần freshclam. Kiểm tra freshclam đang chạy:
sudo systemctl status clamav-freshclam
# Nếu không chạy:
sudo systemctl enable --now clamav-freshclam
Log tập trung. Nếu quản lý nhiều server, gửi log LMD về một chỗ. Mình dùng logger trong cron để đẩy vào syslog, sau đó rsyslog forward về log server trung tâm. Khi có incident, tìm trên một chỗ thay vì SSH từng máy.
Kiểm tra nhanh sau khi setup
# Tạo file test EICAR (malware test string, vô hại)
echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > /tmp/eicar-test.php
# Chạy scan
maldet -a /tmp/eicar-test.php
# Nếu output có hits: 1 là LMD + ClamAV đang hoạt động đúng
# Dọn test file
rm /tmp/eicar-test.php
Setup xong, bạn có một lớp bảo vệ chủ động. LMD không phải silver bullet — webshell zero-day hay mã obfuscate tinh vi vẫn có thể lọt qua — nhưng 95% các vụ tấn công thông thường vào shared hosting và WordPress sẽ bị chặn hoặc phát hiện trước khi gây thiệt hại nghiêm trọng.

