Bối cảnh: Server vừa online đã bị bot tấn công
Vừa dựng xong một VPS với IP public? Chỉ 10 đến 15 phút sau, bot quét cổng từ khắp nơi đã bắt đầu gõ cửa. Qua nhiều đợt audit hạ tầng thực tế, mình thấy lỗi phổ biến nhất là để cổng SSH và web server mở toang mà không dựng bất kỳ cơ chế phòng thủ chủ động nào.
Thử mở file log SSH (/var/log/auth.log trên Ubuntu hoặc /var/log/secure trên RHEL/CentOS) hay log Nginx (/var/log/nginx/access.log). Bạn sẽ thấy trung bình hàng nghìn lượt đăng nhập thất bại mỗi ngày. Kẻ tấn công liên tục thử các user phổ biến như root, admin, test, hoặc rà quét những path nhạy cảm như /.env, /wp-login.php, /phpmyadmin.
Fail2ban sinh ra để xử lý triệt để bài toán này. Cơ chế vận hành rất trực diện:
- Theo dõi log: Đọc liên tục các file log hệ thống theo thời gian thực.
- Bắt mẫu hành vi: Dùng regex trong bộ lọc (filter) để gom các lần xác thực thất bại hoặc request đáng ngờ.
- Khóa IP: Khi một IP chạm ngưỡng sai (
maxretry) trong khoảng thời gian nhất định (findtime), Fail2ban tự gọi firewall (iptables, nftables hoặc UFW) để cấm cửa IP đó trong thời hạn cấu hình (bantime).
Cài đặt Fail2ban trên Linux
Fail2ban có sẵn trong repository chính thức của hầu hết các distro Linux. Quá trình cài đặt chỉ tốn chưa đầy 1 phút.
1. Trên Ubuntu / Debian
sudo apt update
sudo apt install fail2ban -y
2. Trên CentOS / RHEL / AlmaLinux / Rocky Linux
sudo dnf install epel-release -y
sudo dnf install fail2ban fail2ban-systemd -y
Cài xong, bật service để Fail2ban khởi động cùng OS:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban
Cấu hình chi tiết bảo vệ SSH và Nginx
Ghi nhớ nguyên tắc quan trọng: không sửa trực tiếp file /etc/fail2ban/jail.conf. File này sẽ bị ghi đè mỗi khi cập nhật package. Hãy sao chép nội dung sang jail.local để tùy biến an toàn.
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
1. Thiết lập cấu hình chung (Global Defaults)
Mở file /etc/fail2ban/jail.local bằng editor quen thuộc:
sudo nano /etc/fail2ban/jail.local
Tìm block [DEFAULT] và cập nhật các thông số nền tảng sau:
[DEFAULT]
# Bỏ qua các IP an toàn (IP văn phòng, IP tĩnh nhà riêng, localhost)
ignoreip = 127.0.0.1/8 ::1 203.0.113.50
# Thời gian khóa mặc định (1h = 1 giờ, 1d = 1 ngày)
bantime = 1h
# Khoảng thời gian theo dõi tích lũy lỗi (10 phút)
findtime = 10m
# Số lần thử sai tối đa trước khi bị chặn
maxretry = 5
# Cơ chế lũy tiến: Tự động phạt nặng IP tái phạm nhiều lần
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w
Tính năng bantime.increment = true cực kỳ đáng giá trong môi trường production. Lần đầu vi phạm, IP bị cấm 1 giờ. Nhưng nếu vừa hết hạn lại tiếp tục tấn công, thời gian phạt sẽ nhân đôi lên 2 giờ, 4 giờ và tối đa lên tới 4 tuần (4w). Cấu hình này bẻ gãy hoàn toàn các đợt brute force kiên trì của botnet.
2. Cấu hình bảo vệ SSH (sshd)
Di chuyển xuống phần [sshd] hoặc thêm đoạn sau vào file jail.local:
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = systemd
maxretry = 3
findtime = 15m
bantime = 24h
Lưu ý: Nếu bạn đổi cổng SSH sang cổng tùy chỉnh (ví dụ 2222), cần sửa thành port = 2222 để Fail2ban chặn đúng port trên firewall.
3. Cấu hình bảo vệ Nginx
Với web server Nginx, chúng ta thường gặp ba kiểu tấn công: brute force HTTP Basic Auth, quét tìm file mã nguồn nhạy cảm và spam request làm nghẽn tài nguyên.
Thêm các jail chuyên dụng sau vào jail.local:
# 1. Chặn Brute Force HTTP Basic Auth (khu vực admin, staging có password)
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 12h
# 2. Chặn bot quét file rò rỉ (.env, .git, wp-admin, phpmyadmin)
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 2
findtime = 10m
bantime = 48h
# 3. Chặn các client vi phạm rate limit cấu hình trong Nginx
[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
findtime = 5m
maxretry = 5
bantime = 1h
4. Tạo Custom Filter chặn bot quét lỗi 404 hàng loạt
Các tool quét tự động thường bắn hàng trăm request mỗi phút để dò file backup (như backup.zip, db.sql). Chúng ta có thể tự viết filter bắt các IP gây ra quá nhiều mã lỗi 404.
Tạo file bộ lọc /etc/fail2ban/filter.d/nginx-404-scan.conf:
[Definition]
failregex = ^<HOST> - .* "(GET|POST|HEAD).*".* 404 .*
ignoreregex =
Khai báo jail mới vào cuối file /etc/fail2ban/jail.local:
[nginx-404-scan]
enabled = true
port = http,https
filter = nginx-404-scan
logpath = /var/log/nginx/access.log
findtime = 1m
maxretry = 20
bantime = 2h
Quy tắc này rất rõ ràng: nếu một IP dính 20 lỗi 404 chỉ trong 1 phút, Fail2ban sẽ lập tức khóa IP đó trong 2 giờ.
Khởi động lại dịch vụ để nạp toàn bộ cấu hình mới:
sudo systemctl restart fail2ban
Giám sát và Vận hành thực tế
CLI fail2ban-client là công cụ chính để bạn theo dõi và kiểm soát toàn bộ hoạt động của các jail.
1. Kiểm tra trạng thái tổng quan các Jail
sudo fail2ban-client status
Output mẫu khi các jail hoạt động bình thường:
Status
|- Number of jail: 4
`- Jail list: nginx-404-scan, nginx-botsearch, nginx-http-auth, sshd
2. Xem danh sách IP đang bị khóa trong từng Jail
Muốn kiểm tra chi tiết jail SSH đã bắt được bao nhiêu bot:
sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 45
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 3
|- Total banned: 12
`- Banned IP list: 198.51.100.23 203.0.113.11 192.0.2.88
3. Cứu nguy: Gỡ khóa khi lỡ tay tự ban IP của chính mình
Nhập sai pass SSH quá số lần cho phép sẽ khiến bạn bị chính server của mình chặn. Khi kết nối qua 4G, mạng dự phòng hoặc Web Console của nhà cung cấp VPS, hãy dùng lệnh sau để mở khóa:
# Gỡ ban cho một IP cụ thể trong jail sshd
sudo fail2ban-client set sshd unbanip 203.0.113.50
# Hoặc mở khóa IP trên toàn bộ các jail đang chạy
sudo fail2ban-client unban 203.0.113.50
4. Theo dõi log hoạt động realtime
Để tận mắt nhìn thấy Fail2ban bắt và chặn IP theo thời gian thực:
sudo tail -f /var/log/fail2ban.log
Mỗi khi có IP vi phạm, log sẽ hiển thị thông báo rõ ràng:
2026-10-07 10:15:22,418 fail2ban.actions [1452]: NOTICE [sshd] Ban 198.51.100.23
2026-10-07 10:20:05,112 fail2ban.actions [1452]: NOTICE [nginx-botsearch] Ban 192.0.2.14
Chỉ mất khoảng 5 phút cấu hình, bạn đã dựng xong một chốt chặn tự động kiên cố. Server sẽ rảnh tay phục vụ người dùng thực thay vì hao tổn CPU cho hàng nghìn request rác mỗi ngày.

