Sau khi đã hardening SSH bằng key-based login, tắt root/password login và giới hạn user được phép SSH, lớp tiếp theo nên có trên VPS public là Fail2ban. Một server có SSH và Nginx mở ra internet gần như chắc chắn sẽ bị bot quét, thử user phổ biến, dò password, scan URL lạ, tìm file backup, tìm endpoint admin hoặc thử khai thác các path quen thuộc.
Bài Fail2ban cho SSH và Nginx: ban tự động, tune jail đi theo hướng production-ready tối thiểu cho Ubuntu 24.04 LTS: cài Fail2ban, hiểu jail/filter/action, bật jail cho SSH, thêm jail cơ bản cho Nginx, phối hợp với UFW, kiểm tra trạng thái ban, unban khi tự chặn nhầm, và tune các giá trị như bantime, findtime, maxretry theo mức rủi ro thật.
Mục tiêu không phải là biến Fail2ban thành “lá chắn tuyệt đối”. Fail2ban không thay thế SSH key, firewall, cập nhật bảo mật, WAF, backup hay code an toàn. Giá trị của Fail2ban là phản ứng tự động dựa trên log: khi một IP có hành vi sai lặp lại trong một khoảng thời gian, server tự động ban IP đó trong một khoảng thời gian nhất định.
1. Hiểu đúng về Fail2ban trước khi cài
1.1. Fail2ban làm gì?
Fail2ban là một service theo dõi log, dùng filter để nhận diện hành vi đáng ngờ, rồi dùng action để ban hoặc unban IP. Với SSH, hành vi phổ biến là đăng nhập sai nhiều lần. Với Nginx, hành vi có thể là brute force Basic Auth, scan URL rác, hit quá nhiều endpoint bị giới hạn, hoặc tạo nhiều lỗi theo pattern cụ thể.
Luồng hoạt động cơ bản:
- Service như SSH hoặc Nginx ghi log.
- Fail2ban đọc log đó thông qua jail.
- Filter nhận diện dòng log nào là lỗi cần tính.
- Nếu một IP vượt
maxretrytrong khoảngfindtime, Fail2ban ban IP đó. - Sau thời gian
bantime, IP được unban nếu cấu hình cho phép.
Điểm hay của Fail2ban là nó dựa trên log thật, không phải đoán mò. Nhưng cũng vì vậy, nếu log path sai, filter sai hoặc service không ghi log như bạn nghĩ, jail sẽ không hoạt động.
1.2. Fail2ban không thay thế SSH hardening
Không nên bật Fail2ban rồi giữ SSH password login cho tiện. Fail2ban chỉ là lớp phản ứng. Lớp nền vẫn phải là:
- Không SSH trực tiếp bằng root.
- Đăng nhập bằng SSH key.
- Tắt password login nếu key đã hoạt động.
- Giới hạn user hoặc group được phép SSH.
- UFW chỉ mở port cần thiết.
- Cập nhật bảo mật định kỳ.
Nói cách khác, Fail2ban nên được đặt sau SSH hardening, không phải dùng để bù cho SSH cấu hình yếu.
1.3. Fail2ban không phải WAF
Fail2ban có thể giúp giảm brute force và một số hành vi scan lặp lại, nhưng nó không thay thế Web Application Firewall. Nếu ứng dụng có SQL injection, XSS, upload file lỗi hoặc plugin WordPress có lỗ hổng, Fail2ban không tự sửa được.
Với Nginx, Fail2ban hữu ích nhất khi bạn có log rõ ràng và pattern dễ nhận diện: Basic Auth fail, scan URL phổ biến, request bị rate limit, hoặc nhiều lỗi 404/403 từ cùng một IP. Nếu muốn chặn tấn công ứng dụng phức tạp, bạn cần thêm WAF, rule ở Cloudflare, hardening app và cập nhật phần mềm.
2. Hiểu jail, filter, action, bantime, findtime và maxretry
2.1. Jail là gì?
Jail là cấu hình ghép ba thứ lại với nhau: log nào cần theo dõi, filter nào dùng để nhận diện lỗi, và action nào dùng để ban IP.
Ví dụ jail sshd thường có ý nghĩa:
- Theo dõi log SSH.
- Dùng filter
sshdđể nhận diện đăng nhập sai. - Khi vượt ngưỡng, ban IP bằng firewall action.
Một jail tốt phải dễ đọc, dễ test và không quá hung hăng. Ban quá nhẹ thì không hiệu quả; ban quá mạnh thì có thể chặn nhầm người dùng hợp lệ.
2.2. Filter là gì?
Filter là tập regex dùng để nhận diện dòng log nào được xem là lỗi. Ví dụ filter SSH nhận diện các dòng như failed password, invalid user hoặc authentication failure.
Không nên tự viết filter phức tạp ngay từ đầu. Fail2ban đã có nhiều filter sẵn cho SSH, Nginx, Apache và nhiều service phổ biến. Với người mới, hãy ưu tiên filter built-in, sau đó dùng fail2ban-regex để test nếu cần custom.
2.3. Action là gì?
Action là cách Fail2ban thực hiện ban/unban. Action có thể dùng iptables, nftables, firewalld, UFW hoặc một cơ chế khác tùy hệ thống.
Với VPS Ubuntu đang dùng UFW, có hai hướng phổ biến:
- Để Fail2ban dùng action mặc định qua iptables/nftables wrapper.
- Cấu hình
banaction = ufwđể Fail2ban thêm rule thông qua UFW.
Với server nhỏ, dùng ufw action dễ hiểu hơn vì bạn có thể nhìn rule bằng UFW. Với server bị tấn công nhiều, quá nhiều rule UFW động có thể khó quản lý hơn; khi đó nên cân nhắc action dựa trên nftables/ipset phù hợp hơn.
2.4. bantime, findtime và maxretry hiểu thế nào?
Ba giá trị quan trọng nhất:
maxretry: số lần lỗi được phép trước khi ban.findtime: khoảng thời gian dùng để đếm lỗi.bantime: thời gian ban IP.
Ví dụ:
maxretry = 5
findtime = 10m
bantime = 1h
Nghĩa là nếu một IP có 5 lần lỗi trong 10 phút, nó bị ban 1 giờ.
Không có bộ số đúng cho mọi server. VPS cá nhân có thể dùng ngưỡng chặt hơn. Website có nhiều người dùng thật, nhiều IP NAT hoặc nhân viên login từ mạng công ty nên tune cẩn thận hơn để tránh false positive.
3. Chuẩn bị trước khi cài Fail2ban
3.1. Kiểm tra SSH, Nginx và UFW hiện tại
Trước khi cài Fail2ban, kiểm tra các service nền:
sudo systemctl status ssh --no-pager
sudo systemctl status nginx --no-pager
sudo ufw status verbose
Nếu SSH hoặc Nginx đang lỗi, xử lý trước. Fail2ban nên được cài trên một hệ thống đã có service nền chạy ổn, không phải dùng để che lỗi cấu hình.
3.2. Kiểm tra log SSH
Trên Ubuntu 24.04 LTS, bạn nên kiểm tra SSH log qua journal:
sudo journalctl -u ssh --since "1 hour ago" --no-pager | tail -n 80
Nếu hệ thống có /var/log/auth.log, kiểm tra thêm:
sudo tail -n 80 /var/log/auth.log || true
Việc biết SSH log đang nằm ở đâu rất quan trọng. Nếu jail SSH trỏ sai backend hoặc sai log path, Fail2ban có thể chạy nhưng không ban được gì.
3.3. Kiểm tra log Nginx
sudo ls -lh /var/log/nginx/
sudo tail -n 50 /var/log/nginx/access.log || true
sudo tail -n 50 /var/log/nginx/error.log || true
Nếu bạn đã tách log theo từng site, kiểm tra log riêng:
sudo tail -n 50 /var/log/nginx/example.com.access.log
sudo tail -n 50 /var/log/nginx/example.com.error.log
Với Fail2ban cho Nginx, log format và log path phải đúng. Nếu Nginx không ghi access/error log như bạn nghĩ, jail sẽ không match.
3.4. Chuẩn bị một IP an toàn nếu có
Nếu bạn có IP cố định tại nhà, IP VPN hoặc IP văn phòng, hãy thêm vào ignoreip để giảm rủi ro tự ban nhầm. Nếu IP của bạn thay đổi liên tục, không nên thêm bừa.
Kiểm tra IP public hiện tại:
curl -4 ifconfig.me
curl -6 ifconfig.me || true
Chỉ thêm IP vào ignore list nếu bạn hiểu nó là IP ổn định.
4. Cài Fail2ban trên Ubuntu 24.04 LTS
4.1. Cài package cần thiết
sudo apt update
sudo apt install -y fail2ban python3-systemd
python3-systemd hữu ích khi Fail2ban đọc log từ systemd journal. Với SSH trên Ubuntu mới, dùng backend systemd thường gọn và rõ hơn so với phụ thuộc hoàn toàn vào file /var/log/auth.log.
4.2. Bật và kiểm tra service
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban --no-pager
Kiểm tra version:
fail2ban-client version
Nếu service fail, đọc log ngay:
sudo journalctl -u fail2ban --since "10 minutes ago" --no-pager
sudo tail -n 120 /var/log/fail2ban.log || true
Không nên cài Fail2ban bằng script lạ hoặc pip đè lên package hệ thống nếu chưa hiểu hệ quả. Với VPS production, ưu tiên package từ Ubuntu và cập nhật đầy đủ trước.
4.3. Kiểm tra client kết nối được server
sudo fail2ban-client ping
sudo fail2ban-client status
Kết quả mong đợi:
Server replied: pong
Nếu fail2ban-client ping không trả pong, Fail2ban server chưa chạy đúng. Hãy xử lý service trước khi tạo jail.
5. Cấu hình jail mặc định sạch bằng jail.d
5.1. Không sửa trực tiếp jail.conf
Fail2ban có file /etc/fail2ban/jail.conf, nhưng không nên sửa trực tiếp file này. File đó có thể bị thay đổi khi package update. Cách sạch hơn là tạo file override trong /etc/fail2ban/jail.d/.
Tạo file local:
sudo nano /etc/fail2ban/jail.d/00-devnook-defaults.local
5.2. Cấu hình default cơ bản
Nội dung:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
# Nếu bạn muốn Fail2ban ban thông qua UFW cho dễ nhìn:
banaction = ufw
# Không gửi email trong cấu hình tối thiểu.
destemail = root@localhost
sender = root@localhost
mta = sendmail
action = %(action_)s
Nếu bạn có IP quản trị cố định, có thể thêm vào ignoreip:
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
Không thêm cả dải IP lớn vào ignoreip chỉ vì tiện. Ignore list quá rộng có thể làm Fail2ban mất tác dụng với một số nguồn tấn công.
5.3. Kiểm tra cấu hình Fail2ban
sudo fail2ban-client -t
Nếu có lỗi, Fail2ban sẽ báo file và dòng liên quan. Sửa xong mới restart.
sudo systemctl restart fail2ban
sudo systemctl status fail2ban --no-pager
6. Bật jail SSH an toàn
6.1. Tạo jail SSH
Tạo file:
sudo nano /etc/fail2ban/jail.d/10-sshd.local
Nội dung:
[sshd]
enabled = true
port = ssh
filter = sshd
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
Nếu bạn đã đổi port SSH, thay port = ssh bằng port thật, ví dụ:
port = 2222
6.2. Restart và kiểm tra jail SSH
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd
Kết quả mong đợi là jail sshd xuất hiện trong danh sách jail đang chạy.
6.3. Kiểm tra log của Fail2ban
sudo tail -n 100 /var/log/fail2ban.log
sudo journalctl -u fail2ban --since "30 minutes ago" --no-pager
Nếu jail không chạy, thường do lỗi backend, sai filter, sai port hoặc Fail2ban không đọc được log SSH.
6.4. Có nên test bằng cách cố login sai?
Không nên test quá tay từ IP chính của bạn, vì bạn có thể tự ban mình. Nếu muốn test, hãy dùng một IP phụ hoặc giảm bantime tạm thời trong môi trường staging.
Cách an toàn hơn là đọc log và kiểm tra jail đang hoạt động:
sudo fail2ban-client status sshd
sudo journalctl -u ssh --since "1 hour ago" --no-pager | tail -n 100
Nếu thật sự cần test, hãy đảm bảo bạn có console provider hoặc một phiên SSH khác từ IP không bị ban.
7. Bật jail Nginx cơ bản
7.1. Nên bật jail Nginx nào trước?
Không nên bật mọi jail Nginx có sẵn cùng lúc. Với VPS nhỏ, nên bắt đầu bằng các jail dễ hiểu:
nginx-http-auth: chặn brute force vào khu vực dùng HTTP Basic Auth.nginx-botsearch: chặn một số hành vi scan URL phổ biến.nginx-limit-req: chỉ dùng nếu bạn đã cấu hìnhlimit_reqtrong Nginx.
Nếu website của bạn không dùng Basic Auth, nginx-http-auth sẽ không có nhiều tác dụng. Nếu bạn chưa cấu hình limit_req, jail nginx-limit-req cũng không có log phù hợp để hoạt động.
7.2. Kiểm tra filter Nginx có sẵn
ls -1 /etc/fail2ban/filter.d/nginx*.conf
Kiểm tra log path Nginx:
ls -lh /var/log/nginx/
sudo nginx -T | grep -nE 'access_log|error_log'
7.3. Tạo jail Nginx basic
Tạo file:
sudo nano /etc/fail2ban/jail.d/20-nginx.local
Nội dung:
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/*error.log
maxretry = 5
findtime = 10m
bantime = 1h
[nginx-botsearch]
enabled = true port = http,https filter = nginx-botsearch logpath = /var/log/nginx/*access.log maxretry = 10 findtime = 10m bantime = 2h
Với server có log riêng theo domain như example.com.access.log và example.com.error.log, pattern /var/log/nginx/*access.log và /var/log/nginx/*error.log thường sẽ match được. Nếu bạn đặt tên log khác, cần sửa lại.
7.4. Restart và kiểm tra jail Nginx
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status nginx-http-auth
sudo fail2ban-client status nginx-botsearch
Nếu jail báo không tìm thấy log file, kiểm tra lại logpath. Nếu jail chạy nhưng không bao giờ có failure, có thể filter không match với log format hiện tại hoặc website không phát sinh loại lỗi mà jail đó theo dõi.
8. Tùy chọn: dùng Nginx limit_req kết hợp Fail2ban
8.1. Khi nào cần limit_req?
limit_req của Nginx giúp giới hạn tốc độ request theo IP ở một số endpoint nhạy cảm. Ví dụ: trang login, XML-RPC, API auth hoặc endpoint dễ bị spam.
Fail2ban có thể đọc log từ các request bị Nginx rate limit, rồi ban IP nếu lặp lại nhiều lần. Cách này tốt hơn việc cố ban mọi 404, vì rate limit phản ánh hành vi rõ hơn.
8.2. Tạo zone limit_req trong Nginx
Mở file trong context http:
sudo nano /etc/nginx/conf.d/10-rate-limit.conf
Nội dung:
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
Ý nghĩa: mỗi IP được phép khoảng 5 request mỗi phút trong zone login_limit.
8.3. Áp dụng cho endpoint nhạy cảm
Ví dụ với WordPress wp-login.php:
location = /wp-login.php {
limit_req zone=login_limit burst=10 nodelay;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
Kiểm tra Nginx:
sudo nginx -t
sudo systemctl reload nginx
Không nên áp dụng rate limit quá chặt cho toàn bộ website. Nếu đặt sai, bạn có thể làm người dùng thật bị 503 hoặc làm bot hợp lệ bị chặn.
8.4. Bật jail nginx-limit-req
Thêm vào /etc/fail2ban/jail.d/20-nginx.local:
[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = /var/log/nginx/*error.log
maxretry = 10
findtime = 10m
bantime = 2h
Restart Fail2ban:
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-limit-req
Chỉ bật jail này khi Nginx thật sự ghi log limit request. Nếu không có log phù hợp, jail sẽ không có gì để xử lý.
9. Quản lý ban, unban và kiểm tra IP
9.1. Xem danh sách jail
sudo fail2ban-client status
Xem chi tiết một jail:
sudo fail2ban-client status sshd
sudo fail2ban-client status nginx-botsearch
Bạn sẽ thấy số failed, số banned và danh sách IP đang bị ban.
9.2. Unban IP khi bị chặn nhầm
Nếu một IP bị ban nhầm trong jail SSH:
sudo fail2ban-client set sshd unbanip 203.0.113.10
Với jail Nginx:
sudo fail2ban-client set nginx-botsearch unbanip 203.0.113.10
Sau đó kiểm tra:
sudo fail2ban-client status sshd
sudo fail2ban-client status nginx-botsearch
9.3. Ban thủ công một IP
Trong một số trường hợp, bạn muốn ban thủ công:
sudo fail2ban-client set sshd banip 203.0.113.20
Không nên biến Fail2ban thành danh sách block thủ công dài vô hạn. Nếu cần block nhiều IP/dải IP lâu dài, hãy dùng firewall, WAF, Cloudflare rule hoặc giải pháp phù hợp hơn.
9.4. Kiểm tra rule UFW
Nếu dùng banaction = ufw, kiểm tra:
sudo ufw status numbered
Nếu không thấy rule như kỳ vọng, kiểm tra log Fail2ban:
sudo tail -n 120 /var/log/fail2ban.log
Không phải mọi action đều hiện giống nhau trong UFW. Nếu dùng action iptables/nftables, cần kiểm tra bằng công cụ tương ứng.
10. Tune jail theo môi trường thật
10.1. Cấu hình nhẹ cho VPS cá nhân
VPS cá nhân, ít người SSH, không có nhiều user thật:
[sshd]
enabled = true
maxretry = 4
findtime = 10m
bantime = 2h
Với SSH key-only, số lần fail hợp lệ thường rất ít. Vì vậy có thể dùng ngưỡng chặt hơn.
10.2. Cấu hình vừa phải cho server có team
Server có nhiều người quản trị hoặc deploy automation:
[sshd]
enabled = true
maxretry = 6
findtime = 10m
bantime = 1h
Team nhiều người dễ có lỗi gõ sai user, sai key, sai port hoặc CI runner cấu hình nhầm. Tune quá chặt có thể gây phiền nếu chưa có quy trình truy cập ổn.
10.3. Cấu hình Nginx không nên quá hung hăng
Với Nginx, false positive dễ xảy ra hơn SSH. Một IP công ty, trường học, quán cà phê hoặc nhà mạng có thể là NAT chung của nhiều người. Nếu một vài người dùng thật hit nhiều 404 hoặc login sai, ban cả IP có thể ảnh hưởng nhiều người.
Vì vậy, các jail Nginx nên bắt đầu nhẹ:
maxretry = 10
findtime = 10m
bantime = 1h
Sau vài ngày xem log, nếu toàn bộ failure rõ ràng là bot, có thể tăng bantime hoặc giảm maxretry.
10.4. Có nên bật recidive jail?
recidive là jail dùng để ban lâu hơn các IP tái phạm nhiều lần. Đây là tính năng mạnh nhưng nên dùng sau khi bạn đã theo dõi Fail2ban vài ngày và chắc rằng jail cơ bản không chặn nhầm.
Ví dụ cấu hình recidive:
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 1w
findtime = 1d
maxretry = 5
Không nên bật recidive ngay ngày đầu nếu bạn chưa quen cách unban, đọc log và kiểm tra false positive.
11. Kiểm tra filter bằng fail2ban-regex
11.1. Vì sao cần fail2ban-regex?
Khi một jail không ban như kỳ vọng, có hai khả năng phổ biến: Fail2ban không đọc đúng log, hoặc filter không match với dòng log thực tế. fail2ban-regex giúp kiểm tra filter với log file cụ thể.
11.2. Test filter SSH với auth log nếu có
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Nếu server chủ yếu dùng systemd journal và không có auth.log, bạn có thể export log ra file tạm:
sudo journalctl -u ssh --since "24 hours ago" --no-pager > /tmp/ssh-journal.log
sudo fail2ban-regex /tmp/ssh-journal.log /etc/fail2ban/filter.d/sshd.conf
11.3. Test filter Nginx
sudo fail2ban-regex /var/log/nginx/example.com.access.log /etc/fail2ban/filter.d/nginx-botsearch.conf
Với error log:
sudo fail2ban-regex /var/log/nginx/example.com.error.log /etc/fail2ban/filter.d/nginx-http-auth.conf
Nếu filter không match, đừng vội tăng maxretry hoặc bật thêm jail. Hãy xem log thực tế có đúng loại lỗi mà filter nhận diện hay không.
12. Theo dõi Fail2ban sau khi chạy
12.1. Xem log Fail2ban hằng ngày
sudo tail -n 200 /var/log/fail2ban.log
Lọc ban/unban:
sudo grep -E 'Ban|Unban|Found' /var/log/fail2ban.log | tail -n 100
Qua vài ngày, bạn sẽ biết jail nào hoạt động thật, jail nào không match và IP nào tái phạm nhiều.
12.2. Xem log theo journal
sudo journalctl -u fail2ban --since "today" --no-pager
Khi Fail2ban fail start hoặc restart, journal thường là nơi đọc nhanh nhất.
12.3. Tạo script kiểm tra nhanh
Tạo script:
sudo nano /usr/local/sbin/fail2ban-quick-status.sh
Nội dung:
#!/usr/bin/env bash
set -euo pipefail
echo "== Fail2ban service =="
systemctl status fail2ban --no-pager || true
echo
echo "== Fail2ban ping =="
fail2ban-client ping || true
echo
echo "== Jails =="
fail2ban-client status || true
echo
echo "== Recent bans =="
grep -E 'Ban|Unban|Found' /var/log/fail2ban.log 2>/dev/null | tail -n 80 || true
Cấp quyền:
sudo chmod +x /usr/local/sbin/fail2ban-quick-status.sh
Chạy:
sudo fail2ban-quick-status.sh
13. Phối hợp Fail2ban với UFW, Cloudflare và reverse proxy
13.1. Fail2ban và UFW
Nếu dùng banaction = ufw, Fail2ban sẽ thêm rule thông qua UFW. Cách này dễ hiểu cho VPS nhỏ, nhưng nếu bị scan rất nhiều, danh sách rule có thể dài và khó đọc.
Kiểm tra UFW:
sudo ufw status verbose
sudo ufw status numbered
Nếu UFW quá nhiều rule động, hãy cân nhắc chuyển sang action khác phù hợp hơn sau khi bạn đã hiểu iptables/nftables.
13.2. Nếu website đứng sau Cloudflare
Nếu Nginx chỉ thấy IP của Cloudflare thay vì IP thật của người dùng, Fail2ban có thể ban nhầm IP Cloudflare hoặc không xử lý đúng nguồn tấn công. Khi dùng reverse proxy/CDN, cần đảm bảo Nginx log được real client IP trước khi áp dụng Fail2ban cho Nginx.
Kiểm tra access log:
sudo tail -n 20 /var/log/nginx/example.com.access.log
Nếu toàn thấy IP thuộc proxy/CDN, hãy cấu hình real IP ở Nginx trước. Không nên bật jail Nginx mạnh khi log chưa ghi đúng IP người dùng.
13.3. Fail2ban ở origin không thay thế rule ở CDN
Nếu bạn dùng Cloudflare, nhiều hành vi scan nên được chặn ở edge bằng WAF/rule/rate limit của Cloudflare trước khi request vào VPS. Fail2ban vẫn hữu ích ở origin, nhưng không nên để mọi traffic xấu đi đến VPS rồi mới ban.
14. Lỗi thường gặp khi dùng Fail2ban
14.1. Fail2ban chạy nhưng không ban IP nào
Kiểm tra:
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo tail -n 120 /var/log/fail2ban.log
sudo journalctl -u ssh --since "1 hour ago" --no-pager
Nguyên nhân thường gặp:
- Jail chưa enabled.
- Log path sai.
- Backend không phù hợp.
- Filter không match log hiện tại.
- Chưa đủ số lần fail trong
findtime.
14.2. Tự ban IP của chính mình
Nếu còn một phiên SSH khác hoặc console:
sudo fail2ban-client set sshd unbanip YOUR_IP
Nếu dùng UFW action, kiểm tra thêm:
sudo ufw status numbered
Sau đó cân nhắc thêm IP cố định của bạn vào ignoreip, hoặc tăng maxretry nếu đang tune quá chặt.
14.3. Jail Nginx ban nhầm người dùng thật
Đọc log trước khi tăng bantime:
sudo grep '203.0.113.10' /var/log/nginx/example.com.access.log | tail -n 100
sudo grep '203.0.113.10' /var/log/fail2ban.log | tail -n 100
Nếu IP đó là NAT chung của công ty/trường học/nhà mạng, một vài request xấu có thể khiến nhiều người dùng bị ảnh hưởng. Với Nginx, nên tune nhẹ hơn SSH.
14.4. Fail2ban không đọc được journal SSH
Kiểm tra backend và package:
dpkg -l | grep python3-systemd
sudo fail2ban-client get sshd backend
sudo journalctl -u ssh --since "1 hour ago" --no-pager | tail -n 50
Nếu cần, cài lại:
sudo apt install -y python3-systemd
sudo systemctl restart fail2ban
14.5. Cấu hình sai làm Fail2ban không start
Luôn test trước khi restart:
sudo fail2ban-client -t
Nếu service fail:
sudo systemctl status fail2ban --no-pager
sudo journalctl -u fail2ban --since "10 minutes ago" --no-pager
Đọc đúng file và dòng lỗi. Đừng xóa toàn bộ cấu hình chỉ vì một jail sai.
14.6. Bật quá nhiều jail cùng lúc
Đây là lỗi rất phổ biến. Bật 10 jail cùng lúc khiến bạn không biết jail nào ban nhầm, filter nào không match, log nào bị đọc sai.
Cách tốt hơn:
- Bật
sshdtrước. - Theo dõi 1-2 ngày.
- Bật
nginx-http-authhoặcnginx-botsearch. - Theo dõi log.
- Chỉ bật
nginx-limit-reqkhi đã có Nginx limit_req thật.
15. Checklist Fail2ban cho SSH và Nginx
15.1. Checklist trước khi cài
- SSH đã hardening cơ bản.
- Nginx đang chạy ổn.
- UFW đã bật và chỉ mở port cần thiết.
- Đã biết SSH log nằm trong journal hoặc
auth.log. - Đã biết Nginx access/error log nằm ở đâu.
- Có console provider hoặc phiên SSH dự phòng khi test.
15.2. Checklist sau khi cài
fail2ban-client pingtrảpong.fail2ban-client statushiển thị jail đang chạy.- Jail
sshdđã enabled. - Jail Nginx chỉ bật những jail thật sự phù hợp.
fail2ban-client -tkhông báo lỗi./var/log/fail2ban.logkhông có lỗi mới.
15.3. Checklist tune jail
- SSH có
maxretrychặt hơn Nginx. - Nginx có
maxretryvừa phải để tránh false positive. bantimekhông quá dài trong giai đoạn mới triển khai.- IP quản trị cố định được đưa vào
ignoreipnếu phù hợp. - Không bật recidive khi chưa theo dõi jail cơ bản.
15.4. Checklist vận hành
- Biết xem trạng thái jail bằng
fail2ban-client status JAIL. - Biết unban IP bằng
fail2ban-client set JAIL unbanip IP. - Biết test filter bằng
fail2ban-regex. - Đọc log Fail2ban định kỳ.
- Kiểm tra false positive sau khi bật jail Nginx.
16. FAQ
16.1. Có cần Fail2ban nếu đã tắt SSH password login?
Có thể vẫn nên dùng. Khi password login đã tắt, Fail2ban không còn là lớp bảo vệ chính cho SSH password nữa, nhưng vẫn giúp giảm log noise, phản ứng với các thử nghiệm lặp lại và hỗ trợ audit. Tuy nhiên, giá trị của Fail2ban sẽ cao hơn nếu server có nhiều service public như Nginx, Basic Auth hoặc endpoint login.
16.2. Fail2ban có làm website nhanh hơn không?
Không trực tiếp. Fail2ban không phải công cụ tối ưu hiệu năng. Nó giúp giảm một số traffic xấu lặp lại, nhưng nếu website chậm do PHP, database, ảnh lớn hoặc thiếu cache, cần tối ưu ở lớp khác.
16.3. Nên dùng UFW action hay iptables/nftables action?
Với VPS nhỏ và người mới, banaction = ufw dễ hiểu. Với server có nhiều ban hoặc traffic lớn, action dựa trên nftables/ipset có thể phù hợp hơn. Bài này chọn hướng dễ vận hành trước, sau đó bạn có thể nâng cấp khi đã có nhu cầu thật.
16.4. Có nên ban vĩnh viễn IP tấn công không?
Không nên mặc định ban vĩnh viễn. IP có thể là NAT, proxy, IP động hoặc sau này được cấp cho người khác. Hãy bắt đầu với bantime theo giờ, rồi dùng recidive hoặc WAF/rule riêng cho IP tái phạm rõ ràng.
16.5. Fail2ban có chặn được DDoS không?
Không. Fail2ban không phải giải pháp chống DDoS. Nó xử lý dựa trên log và phản ứng sau khi request đã đến server. Với DDoS hoặc traffic lớn, cần dùng CDN, provider protection, rate limit ở edge, WAF hoặc kiến trúc mạng phù hợp.
16.6. Có nên bật tất cả jail Nginx có sẵn không?
Không. Chỉ bật jail phù hợp với log và tính năng website đang dùng. Bật quá nhiều jail dễ gây false positive, khó debug và làm bạn không biết rule nào đang chặn người dùng.
16.7. Sau bài này nên học gì tiếp?
Sau khi có Fail2ban, bước tiếp theo nên là backup chiến lược. Hardening và ban tự động giúp giảm rủi ro bị tấn công, nhưng backup và restore drill mới là đường lui khi có sự cố thật.
17. Kết luận
Fail2ban cho SSH và Nginx là một lớp phòng thủ thực dụng cho VPS public. Nó không thay thế SSH hardening, firewall, cập nhật bảo mật, WAF hay backup, nhưng giúp server tự phản ứng với các hành vi sai lặp lại dựa trên log thật.
Trong bài này, bạn đã cài Fail2ban trên Ubuntu 24.04 LTS, cấu hình default bằng file trong jail.d, bật jail sshd, thêm jail Nginx cơ bản, hiểu cách tune bantime, findtime, maxretry, kiểm tra trạng thái bằng fail2ban-client, unban IP khi cần, và dùng fail2ban-regex để kiểm tra filter.
Khi dùng đúng cách, Fail2ban giúp giảm brute force, giảm log noise và tạo thêm một lớp tự vệ cho VPS. Nhưng điều quan trọng nhất vẫn là vận hành có kiểm chứng: bật từng jail, đọc log, theo dõi false positive, tune dần theo môi trường thật và luôn biết cách rollback hoặc unban khi cần.

