Security

Bảo mật SSH với Fail2Ban trên VPS Ubuntu và Debian

Mở dashboard của một VPS Linux phơi ra internet, kiểu gì bạn cũng thấy log SSH đầy kẻ thử mật khẩu từ khắp nơi. Thay vì ngồi canh thủ công, cách gọn nhất là để Fail2Ban tự động chặn IP sau vài lần thử sai. Bài này hướng dẫn cài đặt Fail2Ban bảo vệ SSH trên VPS Ubuntu 24.04 LTS và Debian 12, từ lúc cài gói đến test xem jail có thực sự khoá được một IP hay không.

  • Fail2Ban đọc log (mặc định /var/log/auth.log trên Ubuntu/Debian) và đếm số lần đăng nhập sai theo từng IP.
  • Cấu hình nên đặt trong /etc/fail2ban/jail.local, không sửa trực tiếp jail.conf.
  • Luôn whitelist IP của bạn bằng ignoreip trước khi bật jail, kẻo tự chặn chính mình.
  • Kiểm tra trạng thái bằng fail2ban-client status sshd để thấy danh sách IP đang bị chặn.

Vì sao nên bật Fail2Ban cho VPS phơi ra internet?

Một VPS mới mở port 22 gần như lập tức bị quét. Kẻ tấn công dùng botnet thử hàng nghìn tổ hợp user/password, phần lớn nhắm vào các tài khoản mặc định như root, admin, oracle. Nếu bạn dùng xác thực bằng mật khẩu, chỉ cần một tài khoản user yếu là đủ để mất máy.

Có nhiều lớp bảo vệ SSH, và chúng bổ trợ cho nhau chứ không thay thế nhau: tắt đăng nhập bằng mật khẩu và dùng SSH key, đổi port, giới hạn user được login, và dùng Fail2Ban để chặn IP có hành vi xấu. Fail2Ban không thay được SSH key, nhưng nó xử lý đúng phần mà key không làm: giảm nhiễu log và giảm tải do brute-force đập vào liên tục.

Điểm hay của Fail2Ban là nhẹ. Nó chỉ là một daemon Python đọc log, không cần agent nặng hay chỉnh kernel. Trên một gói VPS Linux 2 GB RAM, Fail2Ban ăn vài chục MB, chạy cùng Nginx và MariaDB vẫn thoải mái.

Yêu cầu trước khi bắt đầu

  • Một VPS chạy Ubuntu 24.04 LTS hoặc Debian 12, đã cập nhật gói.
  • User có quyền sudo (không cần đăng nhập thẳng bằng root).
  • Đã biết IP công khai của mình để whitelist. Kiểm tra bằng curl -4 ifconfig.me.
  • Nếu VPS còn xác thực SSH bằng mật khẩu, nên chuẩn bị sẵn SSH key, vì đây là thời điểm tốt để chuyển.
  • Quyền truy cập console/out-of-band qua panel nhà cung cấp, phòng trường hợp tự chặn mất SSH.

Bước 1 - Cài đặt Fail2Ban bảo vệ SSH trên VPS

Cài gói từ repo chính thức của distro. Ubuntu và Debian đều có sẵn Fail2Ban trong repo, không cần thêm PPA.

# Ubuntu 24.04 / Debian 12
sudo apt update
sudo apt install -y fail2ban

Gói cài xong sẽ tự tạo service systemd và bật lên. Kiểm tra ngay:

systemctl status fail2ban

Output mong đợi có dòng active (running). Nếu service báo lỗi, xem log bằng journalctl -u fail2ban -n 50 --no-pager.

Fail2Ban mặc định đã có sẵn một jail tên sshd trong /etc/fail2ban/jail.conf, nhưng file đó sẽ bị ghi đè mỗi lần nâng cấp gói. Vì vậy đừng sửa trực tiếp. Ta sẽ ghi đè bằng jail.local.

Bước 2 - Tạo jail.local cấu hình cho sshd

File jail.local được Fail2Ban đọc sau jail.conf, nên mọi giá trị khai ở đây sẽ thắng. Đây là chỗ riêng biệt bạn nên chỉnh.

sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
# IP hiếm khi bị chặn
ignoreip = 127.0.0.1/8 ::1 203.0.113.10/32
# Thời gian chặn (giây). 1h = 3600
bantime  = 3600
# Khoảng thời gian đếm số lần sai (giây)
findtime = 600
# Số lần sai tối đa trước khi bị chặn
maxretry = 5

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = systemd
EOF

Vài điểm cần hiểu cho đúng, kẻo cấu hình xong mà không hoạt động:

  • ignoreip: thay 203.0.113.10/32 bằng IP thật của bạn (lấy ở bước yêu cầu). Đây là dòng cứu mạng, đừng bỏ qua.
  • bantime / findtime / maxretry: với giá trị trên, kẻ tấn công sai 5 lần trong 10 phút sẽ bị chặn 1 giờ.
  • backend = systemd: đọc log qua journald. Trên Ubuntu 24.04 và Debian 12 với systemd, đây là backend ổn định hơn đọc thẳng file log, tránh lỗi khi log rotate.

Nếu bạn đổi port SSH mặc định sang số khác, sửa dòng port = ssh thành port = 2222 (hoặc port bạn dùng). Khai sai port thì Fail2Ban sẽ thêm rule sai và không chặn được gì.

Bước 3 - Nạp lại cấu hình và kiểm tra jail

Sau khi sửa file, nạp lại cấu hình và xem jail sshd có chạy không.

sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

Output của lệnh thứ ba sẽ giống dạng:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 2
|  |- Total failed:     47
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   198.51.100.23

Nếu Banned IP list có IP nghĩa là jail đã hoạt động thật. Còn nếu lệnh fail2ban-client status sshd báo không tìm thấy jail, kiểm tra lại tên section [sshd] trong jail.local và chạy sudo fail2ban-client -t để xem lỗi cú pháp.

Bước 4 - Test xem Fail2Ban có thực sự chặn không

Đừng tin vào việc "nó chạy rồi là xong". Hãy thử từ một máy khác (không phải máy bạn đang SSH) để xác nhận cơ chế chặn hoạt động. Cách nhanh nhất là cố tình đăng nhập sai vài lần rồi kiểm tra danh sách chặn.

# Từ máy thử, cố tình sai mật khẩu 6 lần
for i in $(seq 1 6); do ssh -o PreferredAuthentications=password \
  -o PubkeyAuthentication=no wrong@YOUR_SERVER_IP; done

# Trên VPS, xem IP vừa bị chặn
sudo fail2ban-client status sshd

IP của máy thử sẽ xuất hiện trong Banned IP list sau khoảng vài chục giây. Nếu muốn gỡ chặn ngay (khi lỡ chặn nhầm đồng nghiệp), dùng:

sudo fail2ban-client set sshd unbanip 198.51.100.23

Và nếu muốn chặn tay một IP:

sudo fail2ban-client set sshd banip 198.51.100.23

Rule Fail2Ban được áp vào tường lửa (iptables/nftables tuỳ hệ thống). Bạn có thể xác nhận bằng sudo iptables -L -n | grep f2b hoặc sudo nft list ruleset | grep f2b. Thấy chuỗi tên chứa f2b-sshd nghĩa là rule đã vào đúng chỗ.

Bước 5 - Whitelist an toàn và tránh tự khoá mình

Lỗi phổ biến nhất khi lần đầu dùng Fail2Ban là tự chặn chính IP của mình, đặc biệt khi bạn làm việc qua VPN có IP thay đổi. Vài mẹo để tránh:

  • Luôn đặt ignoreip với IP hiện tại hoặc dải IP của VPN công ty trước khi restart.
  • Nếu có nhiều kỹ thuật viên, whitelist cả giải IP văn phòng (ví dụ 203.0.113.0/24).
  • Giữ một kênh console qua panel hoặc IPKVM để vào được máy dù SSH bị chặn.
  • Đặt bantime ban đầu ngắn (1 giờ) rồi nâng lên nếu thấy ổn.

Với VPS gửi mail hoặc chạy automation mà bạn truy cập từ nhiều IP động, nên dùng kết hợp whitelist IP tĩnh và tăng maxretry nhẹ nhàng thay vì chặn quá gắt. Nếu dự án của bạn chạy nhiều dịch vụ đặc thù, một VPS SMTP hay VPS automation có thể cần chính sách chặn khác với máy chủ web thông thường.

Bước 6 - Tinh chỉnh và kết hợp lớp bảo vệ khác

Fail2Ban một mình chỉ là lớp chặn dựa trên hành vi. Muốn VPS an toàn thật, nên ghép thêm vài thứ.

Thứ nhất, chuyển SSH sang xác thực bằng key và tắt đăng nhập mật khẩu trong /etc/ssh/sshd_config:

sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo systemctl restart ssh

Kiểm tra trước khi đóng phiên SSH hiện tại để chắc chắn key còn đăng nhập được, tránh tự khoá mình ra ngoài.

Thứ hai, nếu bạn đã dùng ufw hoặc firewalld, Fail2Ban sẽ tự thêm rule chặn qua action tương ứng. Trên Ubuntu, action mặc định dùng iptables khá ổn. Trên VPS traffic cao, có thể để Fail2Ban làm việc phát hiện và chỉnh bantime dài hơn, còn tường lửa đảm nhiệm lọc tĩnh.

Thứ ba, đọc hành vi đăng nhập định kỳ để tinh chỉnh. Lệnh hay dùng:

# Top IP đăng nhập sai nhiều nhất
sudo grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head

# Lệnh đăng nhập thành công
last -a | head

Nhìn vào dữ liệu này vài tuần, bạn sẽ biết có cần tăng maxretry, bật thêm jail (nginx, recidive) hay không. Fail2Ban có jail recidive để chặn kẻ tái phạm lâu hơn, rất đáng bật nếu VPS bị quét liên tục.

Xử lý lỗi thường gặp

1. Jail sshd không hoạt động, status báo "No file found". Nguyên nhân thường do logpath sai hoặc backend không khớp. Trên Ubuntu 24.04 và Debian 12, để backend = systemd. Kiểm tra journalctl -u ssh -n 20 xem log SSH có ghi ra journal không.

2. Bị chặn nhưng IP không vào iptables/nftables. Do bạn chọn action không phù hợp môi trường. Chạy sudo fail2ban-client -d | grep -i banaction để xem action đang dùng, kiểm tra rule tương ứng bằng nft list ruleset | grep f2b.

3. Restart fail2ban báo lỗi cú pháp trong jail.local. Dùng sudo fail2ban-client -t để xem dòng lỗi, sau đó xem lại phần [DEFAULT], chú ý dấu cách và định dạng.

4. Vẫn bị brute-force dù Fail2Ban đã chặn. Fail2Ban chặn sau vài lần sai, không chặn từ lần đầu. Nếu log còn đầy, xem lại maxretry và đảm bảo bạn đã giảm bề mặt tấn công bằng SSH key và đổi port.

Câu hỏi thường gặp

Fail2Ban có thay thế SSH key và xác thực mật khẩu mạnh không?

Không. Fail2Ban chỉ chặn theo hành vi sau vài lần đăng nhập sai, nên nó là lớp bổ sung. Cách bảo vệ SSH đúng là dùng key ED25519, tắt PasswordAuthentication, rồi thêm Fail2Ban để chặn IP xấu.

Bao nhiêu lần đăng nhập sai thì một IP bị chặn?

Mặc định trong bài này là 5 lần sai trong 10 phút, chặn 1 giờ. Bạn chỉnh bằng maxretry, findtimebantime trong jail.local.

Làm sao biết IP nào đang bị Fail2Ban chặn?

Chạy sudo fail2ban-client status sshd. Phần Banned IP list liệt kê chính xác các IP hiện bị chặn, còn Total banned là tổng số lượt chặn.

Tôi sợ tự chặn IP của mình thì xử lý thế nào?

Khai IP của bạn trong ignoreip trước khi restart Fail2Ban. Nếu đã lỡ bị chặn, vào qua console rồi chạy sudo fail2ban-client set sshd unbanip <IP>.

Fail2Ban có làm chậm VPS không?

Rất nhẹ. Nó chỉ đọc log và thêm rule tường lửa, tiêu tốn vài chục MB RAM. Chạy song song Nginx, PHP-FPM hay MariaDB trên VPS 2 GB vẫn ổn.

Nên dùng Fail2Ban hay CrowdSec?

Fail2Ban đơn giản, chạy offline, đủ dùng cho một VPS đơn lẻ. CrowdSec mạnh hơn khi bạn có nhiều máy và muốn chia sẻ danh sách IP xấu giữa các node. Nhiều sysadmin bắt đầu bằng Fail2Ban rồi cân nhắc nâng cấp sau.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.