Hướng dẫn cấu hình Fail2ban trên CyberPanel để chặn brute force FTP và bot quét website
- 19-03-2026
- Toanngo92
- 0 Comments
Khi vận hành website bằng CyberPanel, đặc biệt là WordPress/WooCommerce, rất dễ gặp 2 nhóm tấn công phổ biến:
- bot brute force FTP, liên tục thử tài khoản như
root,ftpuser,www-data,apache,backup… - crawler hoặc bot quét các URL động trên website, ví dụ:
?add_to_wishlist=...&_wpnonce=...&action=yith-woocompare-add-product&id=...
Bài viết này hướng dẫn cách dùng Fail2ban để xử lý đúng trong môi trường CyberPanel + Pure-FTPd + log domain nằm trong /home/<domain>/logs/.
Mục lục
1. Fail2ban là gì và vì sao nên dùng
Fail2ban là công cụ theo dõi log, phát hiện các hành vi truy cập bất thường, rồi tự động ban IP thông qua firewall.
Nó đặc biệt hữu ích khi:
- FTP bị brute force
- SSH bị dò mật khẩu
- website bị bot spam request lặp lại
- cần tự động chặn IP mà không phải ngồi xem log thủ công
Lưu ý quan trọng: Fail2ban không phải lớp bảo vệ đầu tiên. Nó chỉ ban IP sau khi request đã vào log. Vì vậy, với các bot web, nên kết hợp thêm Nginx hoặc ModSecurity để chặn sớm hơn.
2. Đặc điểm môi trường CyberPanel cần hiểu trước
Trong thực tế triển khai với CyberPanel, có vài điểm rất dễ gây nhầm:
2.1. Log website không nằm ở /var/log/nginx/access.log
Với CyberPanel, log website thường nằm trong:
/home/<domain>/logs/
Ví dụ:
/home/<domaincuaban.com>/logs/
Trong đó file access log hiện tại có thể là:
/home/<domaincuaban.com>/logs/<domaincuaban.com>.access_log
2.2. Pure-FTPd có thể log theo nhiều kiểu
Ban đầu nhiều người sẽ thử bám vào:
/var/log/auth.log
Nhưng với Pure-FTPd trên CyberPanel, log brute force FTP thực tế thường lại xuất hiện rõ nhất trong:
journalctl -u pure-ftpd-mysql
và có dạng như:
([email protected]) [WARNING] Authentication failed for user [common_user]
Đây là điểm rất quan trọng, vì nếu bám sai nguồn log thì Fail2ban sẽ chạy nhưng không match gì cả.
3. Cài Fail2ban
Trên Ubuntu/Debian:
apt update
apt install fail2ban -y
Bật tự khởi động cùng server:
systemctl enable fail2ban
systemctl start fail2ban
Kiểm tra trạng thái:
systemctl status fail2ban
Kiểm tra có auto start không:
systemctl is-enabled fail2ban
Nếu trả về enabled thì sau khi reboot server, Fail2ban sẽ tự chạy lại.
4. Trường hợp 1: Chặn brute force FTP bằng Fail2ban
4.1. Dấu hiệu nhận biết
Khi kiểm tra log, có thể thấy các dòng như:
pure-ftpd: pam_unix(pure-ftpd:auth): authentication failure
pure-ftpd: pam_listfile(pure-ftpd:auth): Refused user root for service pure-ftpd
pure-ftpd: pam_unix(pure-ftpd:auth): check pass; user unknown
Hoặc trong journal:
([email protected]) [WARNING] Authentication failed for user [commonuser]
([email protected]) [WARNING] Authentication failed for user [ftpuser]
Điều này cho thấy server đang bị bot dò tài khoản FTP.
4.2. Vì sao không nên dùng auth.log cho case này
Ban đầu có thể thử tạo filter cho:
/var/log/auth.log
Nhưng thực tế log dạng PAM thường không có IP usable, ví dụ:
rhost=
Khi đó Fail2ban không có <HOST> để ban IP.
Vì vậy, với Pure-FTPd trên CyberPanel, hướng đúng là dùng:
backend = systemdjournalmatch = _SYSTEMD_UNIT=pure-ftpd-mysql.service
4.3. Tạo filter cho FTP
Tạo file:
nano /etc/fail2ban/filter.d/pure-ftpd-auth.conf
Nội dung:
[Definition]
failregex = ^.*pure-ftpd\[\d+\]: \(\?@<HOST>\) \[WARNING\] Authentication failed for user \[.*\]\s*$
ignoreregex =
Filter này được thiết kế theo đúng format log journal của Pure-FTPd trong môi trường thực tế.
4.4. Tạo jail cho FTP
Mở file:
nano /etc/fail2ban/jail.local
Thêm nội dung:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 103.154.177.166
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true port = ssh logpath = /var/log/auth.log maxretry = 5 findtime = 600 bantime = 86400
[pure-ftpd]
enabled = true filter = pure-ftpd-auth backend = systemd journalmatch = _SYSTEMD_UNIT=pure-ftpd-mysql.service maxretry = 3 findtime = 3600 bantime = 86400 port = ftp,ftp-data,ftps,30000:40210
Lưu ý:
ignoreipnên có IP quản trị của bạn để tránh tự ban chính mìnhfindtime = 3600phù hợp với kiểu brute force chậmmaxretry = 3nghĩa là sai 3 lần trong 1 giờ sẽ bị ban30000:40210là ví dụ theo range passive port đang dùng; cần sửa cho đúng server nếu khác
4.5. Test regex trước khi restart
Đổ journal ra file tạm:
journalctl -u pure-ftpd-mysql --since "2 hours ago" > /tmp/pure-ftpd-journal.log
Test filter:
fail2ban-regex /tmp/pure-ftpd-journal.log /etc/fail2ban/filter.d/pure-ftpd-auth.conf
Nếu đúng, sẽ thấy có match.
4.6. Restart và kiểm tra
systemctl restart fail2ban
fail2ban-client status
fail2ban-client status pure-ftpd
Nếu hoạt động tốt, bạn sẽ thấy:
Currently failedCurrently bannedBanned IP list
Ví dụ thực tế:
Currently banned: 1
Banned IP list: 222.73.48.210
5. Trường hợp 2: Chặn bot quét website theo query param trên WooCommerce
5.1. Dấu hiệu nhận biết
Trong access log của domain, có thể thấy request kiểu:
GET /shop/?add_to_wishlist=4768&_wpnonce=cc56cd239d
GET /product-category/.../?add_to_wishlist=3888&_wpnonce=58dba9be95&action=yith-woocompare-add-product&id=4857
User-Agent: meta-externalagent/1.1
Đây là crawler của Meta/Facebook đang follow các link động wishlist/compare mà HTML đã render ra.
5.2. Vì sao điều này nguy hiểm
Những request này:
- đi qua PHP/WordPress
- có thể chạm vào logic compare/wishlist
- sinh tải DB và CPU
- có thể gây timeout hoặc tăng load bất thường
Đây không hẳn là “hack” theo nghĩa cổ điển, nhưng là một dạng crawl rất không mong muốn.
5.3. Xác định đúng file log website trên CyberPanel
Không dùng:
/var/log/nginx/access.log
Mà kiểm tra:
ls -lah /home/<domaincuaban.com>/logs
Ví dụ file access log hiện tại là:
/home/<domaincuaban.com>/logs/<domaincuaban.com>.access_log
Đọc thử đúng file đó:
tail -f /home/<domaincuaban.com>/logs/<domaincuaban.com>.access_log | grep meta-externalagent
Nếu grep toàn thư mục sẽ gặp lỗi kiểu:
Binary file (standard input) matches
vì có cả file .gz.
5.4. Tạo filter cho bot wishlist/compare
Tạo file:
nano /etc/fail2ban/filter.d/nginx-wishlist-bot.conf
Nội dung:
[Definition]
failregex = ^<HOST> - - \[.*\] "(GET|POST) .*[\?\&](add_to_wishlist=|_wpnonce=|action=yith-woocompare-add-product).*" \d+ .* ".*" ".*meta-externalagent.*"$
ignoreregex =
Filter này bám đúng log thực tế:
- có query
add_to_wishlist - hoặc
_wpnonce - hoặc
action=yith-woocompare-add-product - và user-agent là
meta-externalagent
5.5. Tạo jail cho bot web
Thêm vào jail.local:
[nginx-wishlist-bot]
enabled = true
port = http,https
filter = nginx-wishlist-bot
logpath = /home/<domaincuaban.com>/logs/<domaincuaban.com>.access_log
maxretry = 2
findtime = 600
bantime = 86400
5.6. Test regex
Tạo file test:
grep 'meta-externalagent' /home/<domaincuaban.com>/logs/<domaincuaban.com>.access_log | tail -50 > /tmp/meta-bot.log
Test:
fail2ban-regex /tmp/meta-bot.log /etc/fail2ban/filter.d/nginx-wishlist-bot.conf
Nếu match > 0 là đúng.
5.7. Restart và kiểm tra
systemctl restart fail2ban
fail2ban-client status nginx-wishlist-bot
6. Vì sao Fail2ban không phải giải pháp duy nhất cho bot web
Fail2ban chỉ ban sau khi:
- request đã đi vào web server
- log đã ghi ra file
- đủ số lần match mới ban
Vì vậy với bot web, Fail2ban nên là lớp bổ sung. Tốt nhất vẫn là:
- chặn bằng Nginx
- hoặc ModSecurity
- hoặc sửa ứng dụng để không expose link GET động
7. Với CyberPanel có ModSecurity, nên chặn thế nào
Nếu server đã có ModSecurity, đây là hướng rất hợp lý để chặn ngay request ngay từ đầu, đặc biệt với case Meta crawler đụng vào wishlist/compare.
Rule mẫu:
SecRule REQUEST_HEADERS:User-Agent "@contains meta-externalagent" \
"id:1001001,phase:2,t:none,deny,status:403,log,auditlog,msg:'Blocked meta bot wishlist/compare query',chain"
SecRule QUERY_STRING "@rx (?:^|&)(add_to_wishlist=|_wpnonce=|action=yith-woocompare-add-product)(?:=|&|$)" "t:none"
Rule này chỉ chặn khi đồng thời:
- user-agent là
meta-externalagent - query string có wishlist/compare param
Ưu điểm:
- không ảnh hưởng người dùng thật
- không cần sửa plugin ngay
- chặn sớm hơn Fail2ban
8. Kiểm tra Fail2ban đang hoạt động đúng hay chưa
Xem toàn bộ jail
fail2ban-client status
Xem FTP
fail2ban-client status pure-ftpd
Xem bot wishlist
fail2ban-client status nginx-wishlist-bot
Xem log
tail -f /var/log/fail2ban.log
9. Những lỗi thường gặp khi cấu hình Fail2ban
9.1. Comment ngay sau giá trị
Sai:
filter = pure-ftpd-auth #pure-ftpd-auth.conf
Đúng:
filter = pure-ftpd-auth
Fail2ban không cho comment như vậy trên cùng dòng.
9.2. Bám sai nguồn log
Ví dụ FTP brute force nhưng lại cố parse auth.log, trong khi IP chỉ hiện rõ ở journalctl.
9.3. Match được nhưng không ban
Nguyên nhân phổ biến là:
maxretryquá caofindtimequá ngắn- bot brute force chậm
Ví dụ IP fail lúc 23:14, 23:36, 23:42 thì với findtime = 300 sẽ không bao giờ ban. Trường hợp này cần tăng lên 3600.
9.4. Test regex sai file
Với CyberPanel, log website phải test đúng file trong /home/<domain>/logs/, không test nhầm /var/log/nginx/access.log.
10. Khuyến nghị thực chiến cho môi trường CyberPanel
Nên làm
- bật Fail2ban cho
sshd - bật Fail2ban cho
pure-ftpd - bật Fail2ban cho bot web ở domain đang bị spam
- dùng ModSecurity để chặn sớm các query độc hại hoặc không mong muốn
- thêm IP quản trị vào
ignoreip
Nên cân nhắc
- giới hạn FTP connection
- đổi từ FTP sang SFTP nếu có thể
- sửa plugin/theme để không render raw URL wishlist/compare bằng GET
11. Mẫu jail.local hoàn chỉnh tham khảo
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 103.154.177.166
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true port = ssh logpath = /var/log/auth.log maxretry = 5 findtime = 600 bantime = 86400
[pure-ftpd]
enabled = true filter = pure-ftpd-auth backend = systemd journalmatch = _SYSTEMD_UNIT=pure-ftpd-mysql.service maxretry = 3 findtime = 3600 bantime = 86400 port = ftp,ftp-data,ftps,30000:40210
[nginx-wishlist-bot]
enabled = true port = http,https filter = nginx-wishlist-bot logpath = /home/<domaincuaban.com>/logs/<domaincuaban.com>.access_log maxretry = 2 findtime = 600 bantime = 86400
12. Kết luận
Trong môi trường CyberPanel, dùng Fail2ban hiệu quả đòi hỏi phải hiểu đúng:
- FTP brute force nên bám vào
journalctl -u pure-ftpd-mysql - bot web theo domain nên bám vào log trong
/home/<domain>/logs/ - Fail2ban là lớp bảo vệ tốt, nhưng với bot web thì nên kết hợp thêm ModSecurity hoặc Nginx
Nếu triển khai đúng, Fail2ban sẽ giúp:
- tự động ban IP brute force FTP
- chặn IP spam request lặp vào website
- giảm tải server
- tăng độ ổn định cho WordPress/WooCommerce





