Fail2ban: cấu hình bảo vệ SSH khỏi dò mật khẩu
Fail2ban đọc nhật ký của các dịch vụ, phát hiện các lần đăng nhập sai lặp lại và chặn tạm thời IP của kẻ tấn công qua tường lửa. Để bảo vệ SSH, chỉ cần cài gói, tạo /etc/fail2ban/jail.local với mục [sshd] (enabled = true, maxretry, findtime, bantime) rồi khởi động lại dịch vụ; trạng thái kiểm tra bằng lệnh fail2ban-client status sshd.
Fail2ban là một daemon theo dõi nhật ký của các dịch vụ, nhận ra những lần đăng nhập thất bại lặp lại và chặn tạm thời địa chỉ IP gây ra chúng. Với SSH, đây là cách bảo vệ đơn giản nhất chống dò mật khẩu: các bot ngừng tấn công máy chủ sau vài lần sai. Dưới đây là cấu hình fail2ban từ lúc cài đặt đến khi kiểm tra các lần chặn và những lỗi thường gặp.
Vì sao cần fail2ban khi đã có khóa SSH
Mọi máy chủ mở cổng 22 đều bắt đầu nhận các lần thử đăng nhập từ bot chỉ vài phút sau khi khởi động. Bạn có thể tự xem:
$ sudo journalctl -u ssh --since "1 hour ago" | grep -c "Failed password"
412
Nếu đăng nhập bằng mật khẩu đã bị tắt và chỉ dùng khóa, gần như không thể đoán được quyền truy cập. Nhưng fail2ban vẫn hữu ích: nó giảm nhiễu trong nhật ký, giảm tải do hàng nghìn kết nối gây ra, và bảo vệ khi cấu hình sai khiến đăng nhập bằng mật khẩu vô tình vẫn được bật. Đây là lớp bảo vệ thứ hai, không thay thế khóa.
Fail2ban hoạt động như thế nào
Logic gồm ba phần:
- Bộ lọc (filter) — tập biểu thức chính quy tìm các dòng đăng nhập thất bại trong nhật ký và trích xuất IP từ đó. Bộ lọc nằm trong
/etc/fail2ban/filter.d/. - Hành động (action) — việc cần làm với kẻ vi phạm: thêm quy tắc vào iptables, nftables, ufw hoặc firewalld. Hành động nằm trong
/etc/fail2ban/action.d/. - Nhà tù (jail) — sự kết hợp giữa bộ lọc, hành động, nguồn nhật ký và ngưỡng. Ví dụ, jail
sshdtheo dõi nhật ký SSH.
Nếu trong khoảng findtime có maxretry lần khớp từ cùng một IP, địa chỉ đó bị chặn trong bantime. Hết thời gian, lệnh chặn được gỡ tự động.
Cài đặt fail2ban
Trên Debian và Ubuntu:
sudo apt update
sudo apt install fail2ban
Trên RHEL, Rocky, AlmaLinux, gói nằm trong kho EPEL:
sudo dnf install epel-release
sudo dnf install fail2ban
Bật tự khởi động và kiểm tra trạng thái dịch vụ:
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
Trên Debian và Ubuntu, jail cho SSH đã được bật sẵn qua /etc/fail2ban/jail.d/defaults-debian.conf. Trong họ RHEL, sau khi cài không có jail nào được bật — phải kích hoạt thủ công.
Nơi lưu cấu hình: jail.conf và jail.local
File chính là /etc/fail2ban/jail.conf, nhưng không nên sửa trực tiếp: khi cập nhật gói, file sẽ bị ghi đè. Cấu hình riêng đặt trong /etc/fail2ban/jail.local hoặc các file /etc/fail2ban/jail.d/*.local. Fail2ban đọc các file theo thứ tự sau, và mỗi file sau ghi đè file trước:
jail.confjail.d/*.confjail.localjail.d/*.local
Đừng sao chép toàn bộ jail.conf sang jail.local — làm vậy sẽ đóng băng các giá trị mặc định cũ. Trong jail.local chỉ ghi những gì bạn thay đổi.
Cấu hình fail2ban cho SSH: jail.local tối thiểu
Tạo file:
sudo nano /etc/fail2ban/jail.local
Và thêm vào:
[DEFAULT]
# Địa chỉ của bạn, không bao giờ bị chặn
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime = 1h
findtime = 10m
maxretry = 5
# Lấy nhật ký từ đâu: journal của systemd hay file
backend = systemd
[sshd]
enabled = true
port = ssh
maxretry = 3
Khởi động lại dịch vụ và kiểm tra jail đã chạy:
$ sudo systemctl restart fail2ban
$ sudo fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sshd
Ý nghĩa các tham số
| Tham số | Ý nghĩa | Ví dụ |
|---|---|---|
enabled | jail có được bật hay không | true |
port | cổng cần chặn đối với kẻ vi phạm | ssh, 2222, ssh,2222 |
maxretry | số lần sai cho phép trước khi bị chặn | 3 |
findtime | khoảng thời gian để đếm các lần sai | 10m |
bantime | thời gian chặn; -1 — vĩnh viễn | 1h, 1d |
ignoreip | địa chỉ và mạng con không bị chặn | 10.0.0.0/8 |
backend | nguồn nhật ký | systemd, auto |
logpath | đường dẫn file nhật ký khi dùng backend file | /var/log/auth.log |
banaction | dùng tường lửa nào để chặn | nftables-multiport, ufw |
Thời gian có thể viết kèm hậu tố: s, m, h, d, w. Số không có hậu tố được tính bằng giây.
backend: systemd hay file
Trên Debian 12 và Ubuntu 24.04 hiện đại, file /var/log/auth.log có thể không tồn tại nếu chưa cài rsyslog: nhật ký SSH chỉ nằm trong journal của systemd. Khi đó cần backend = systemd, nếu không fail2ban sẽ không khởi động được và báo lỗi không tìm thấy file nhật ký. Còn nếu có rsyslog, có thể dùng cách dựa trên file:
[sshd]
enabled = true
backend = auto
logpath = /var/log/auth.log
Trên hệ thống họ RHEL, file tương ứng là /var/log/secure.
SSH trên cổng không chuẩn
Nếu sshd lắng nghe trên cổng 2222 chẳng hạn, hãy khai báo cổng đó trong jail — nếu không, fail2ban sẽ chặn cổng 22 còn cuộc tấn công vẫn tiếp tục trên 2222:
[sshd]
enabled = true
port = 2222
Để chặn kẻ vi phạm trên tất cả các cổng cùng lúc, dùng hành động iptables-allports hoặc nftables-allports qua tham số banaction.
Chọn tường lửa: iptables, nftables, ufw, firewalld
Mặc định trên Debian dùng banaction = nftables (phiên bản cũ dùng iptables), còn trên RHEL là firewalld. Nếu máy chủ đang dùng ufw, nên để các lệnh chặn hiển thị trong ufw:
[DEFAULT]
banaction = ufw
Với firewalld:
[DEFAULT]
banaction = firewallcmd-rich-rules
Để kiểm tra các quy tắc chặn thực sự đã xuất hiện, dùng sudo nft list ruleset | grep f2b hoặc sudo iptables -L -n | grep f2b: fail2ban tạo các chuỗi có tiền tố f2b-.
Kiểm tra hoạt động: fail2ban-client status
Công cụ quản lý chính là fail2ban-client. Trạng thái của một jail:
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 147
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 4
|- Total banned: 38
`- Banned IP list: 45.148.10.12 92.118.39.7 185.224.128.40 218.92.0.112
Ở đây thấy số lần sai trong cửa sổ hiện tại, số IP đang bị chặn và danh sách cụ thể. Để kiểm tra thực tế, hãy thử đăng nhập sai vài lần từ một máy khác (không phải máy có trong ignoreip) — sau lần thử thứ ba, kết nối sẽ không còn được thiết lập.
Nhật ký của chính fail2ban nằm trong /var/log/fail2ban.log:
$ sudo tail -n 3 /var/log/fail2ban.log
2026-10-14 09:12:41,118 fail2ban.filter [812]: INFO [sshd] Found 218.92.0.112
2026-10-14 09:12:44,302 fail2ban.filter [812]: INFO [sshd] Found 218.92.0.112
2026-10-14 09:12:47,551 fail2ban.actions [812]: NOTICE [sshd] Ban 218.92.0.112
Cách gỡ ban IP trong fail2ban
Nếu bạn tự chặn chính mình hoặc đồng nghiệp, hãy gỡ ban từ console của máy chủ (qua bảng điều khiển nhà cung cấp hoặc từ một IP khác):
sudo fail2ban-client set sshd unbanip 203.0.113.25
Gỡ tất cả các lần chặn trong mọi jail:
sudo fail2ban-client unban --all
Chặn thủ công một địa chỉ mà không chờ bộ lọc kích hoạt:
sudo fail2ban-client set sshd banip 198.51.100.7
Để sự cố không lặp lại, hãy thêm địa chỉ tĩnh hoặc mạng văn phòng của bạn vào ignoreip.
Tăng dần thời gian chặn với kẻ tái phạm
Nhiều bot quay lại ngay sau khi được gỡ chặn. Từ phiên bản 0.11, fail2ban hỗ trợ tăng thời gian chặn cho kẻ tái phạm:
[DEFAULT]
bantime = 1h
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w
Mỗi lần chặn tiếp theo của cùng một IP sẽ dài hơn lần trước, nhưng không quá bốn tuần. Phương án thay thế cho các phiên bản cũ là jail recidive, đọc chính nhật ký của fail2ban và chặn lâu các địa chỉ đã xuất hiện nhiều lần:
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 1w
findtime = 1d
maxretry = 5
Kiểm tra bộ lọc: fail2ban-regex
Nếu jail đang chạy nhưng không chặn ai, hãy kiểm tra xem bộ lọc có thực sự tìm thấy dòng nào trong nhật ký không. Với file nhật ký:
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Với journal của systemd:
sudo fail2ban-regex systemd-journal sshd
Trong kết quả, hãy xem dòng Lines: ... matched. Nếu số dòng khớp bằng không, bộ lọc không phù hợp với định dạng nhật ký hoặc nguồn được chỉ định sai. Trước khi khởi động lại, nên kiểm tra cú pháp toàn bộ cấu hình:
sudo fail2ban-client -t
Lỗi thường gặp
- Dịch vụ không khởi động: «Have not found any log file for sshd jail». Không có
/var/log/auth.log. Đặtbackend = systemdhoặc cài rsyslog. - Trạng thái có các lần chặn nhưng tấn công vẫn tiếp diễn. Sai cổng (SSH đã được chuyển cổng) hoặc quy tắc tường lửa bị một quy tắc cho phép đứng trước che lấp. Kiểm tra
portvà kết quả củanft list ruleset. - Thay đổi không có tác dụng. Bạn sửa
jail.conf, nhưngjail.localhoặcjail.d/*.locallại có giá trị khác. Xem giá trị thực tế đang dùng:sudo fail2ban-client get sshd maxretry. - Tự chặn chính mình. Gỡ ban qua console và thêm IP vào
ignoreip. - Fail2ban trong Docker không thấy tấn công. Các cổng của container được công bố qua chuỗi DOCKER, vốn bỏ qua INPUT. Với các dịch vụ này, dùng
chain = DOCKER-USERtrong hành động.
Những việc khác cần làm để bảo vệ SSH
Fail2ban hoạt động tốt nhất cùng các biện pháp cơ bản trong /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
Sau khi sửa, kiểm tra cấu hình bằng sudo sshd -t rồi khởi động lại dịch vụ. Đừng đóng phiên hiện tại cho tới khi xác nhận đăng nhập mới bằng khóa hoạt động. Ngoài ra có thể giới hạn truy cập SSH ở tầng tường lửa chỉ cho các địa chỉ cần thiết.
Tóm lại
Cấu hình fail2ban gồm vài bước: cài gói, tạo jail.local với mục [sshd], chọn đúng backend và cổng, đặt maxretry, findtime và bantime, thêm địa chỉ của bạn vào ignoreip, rồi kiểm tra bằng fail2ban-client status sshd. Kết hợp với việc chỉ đăng nhập bằng khóa, cách này bảo vệ SSH khỏi dò mật khẩu một cách đáng tin cậy. Bảo vệ máy chủ và fail2ban được thực hành cụ thể trong khóa học Linux.
Câu hỏi thường gặp
Có cần fail2ban khi đã tắt đăng nhập bằng mật khẩu không?
Không bắt buộc, nhưng vẫn hữu ích: nó loại bỏ hàng nghìn lần thử rác khỏi nhật ký, giảm tải và bảo vệ bạn nếu ai đó lại vô tình bật đăng nhập bằng mật khẩu.
Làm sao xem tất cả IP bị chặn trong mọi jail?
Chạy sudo fail2ban-client banned — lệnh hiển thị danh sách địa chỉ bị chặn theo từng jail. Với một jail cụ thể, dùng fail2ban-client status sshd.
Các lần chặn có còn sau khi khởi động lại máy không?
Có. Fail2ban lưu các lần chặn trong cơ sở dữ liệu SQLite (/var/lib/fail2ban/fail2ban.sqlite3) và khôi phục những lệnh chặn còn hiệu lực khi khởi động, trừ khi tham số dbpurgeage đã xóa chúng trước đó.
Fail2ban có bảo vệ được cả dịch vụ khác ngoài SSH không?
Có, đi kèm sẵn bộ lọc cho nginx, Apache, Postfix, Dovecot và nhiều dịch vụ khác. Chỉ cần bật jail tương ứng trong jail.local, ví dụ [nginx-http-auth] với enabled = true.
Fail2ban khác gì so với giới hạn trong tường lửa?
Tường lửa cho phép hoặc cấm địa chỉ theo quy tắc cố định, còn fail2ban chặn động những ai có hành vi đáng ngờ trong nhật ký. Hai cơ chế này thường được kết hợp: danh sách cho phép trong tường lửa và fail2ban cho phần còn lại.
Chủ đề này được giảng chi tiết kèm thực hành trong khóa học “Linux: с нуля до уверенного администрирования”.
Đến khóa học