Cấu hình PAM trên Linux: Tự động khóa tài khoản và siết chính sách mật khẩu

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Ba lớp phòng thủ đăng nhập trên hệ điều hành Linux

Mỗi ngày, một máy chủ mở cổng SSH công khai có thể hứng chịu từ 5.000 đến 20.000 lượt dò mật khẩu từ các botnet. Ngoài SSH, server còn nhiều điểm chạm khác: lệnh sudo/su khi làm việc qua terminal, dịch vụ SFTP hoặc phiên đăng nhập qua console vật lý. Để chặn đứng nguy cơ này, kỹ sư hệ thống thường dùng 3 phương án:

  • Cách 1: Cấu hình riêng lẻ ở từng daemon (Application-level). Chỉnh trực tiếp thông số trong sshd_config (như MaxAuthTries 3) hoặc vsftpd.conf. Cách này dễ làm. Tuy nhiên, nó phân mảnh và bỏ sót các kênh truy cập nội bộ.
  • Cách 2: Giám sát log bằng Fail2ban. Fail2ban đọc file /var/log/auth.log. Khi một IP nhập sai quá ngưỡng, nó tự động đẩy rule chặn IP đó vào iptables hoặc nftables.
  • Cách 3: Chặn trực tiếp tại tầng xác thực lõi (PAM – Pluggable Authentication Modules). PAM là trạm kiểm soát danh tính trung tâm của Linux kernel space. Dù user gõ pass qua SSH, switch user bằng su, hay chạy lệnh qua sudo, mọi ứng dụng đều phải chuyển yêu cầu sang PAM xử lý theo cùng một bộ quy tắc.

So sánh thực tế: Khi nào Fail2ban hụt hơi trước PAM?

Mỗi giải pháp nhắm tới một vị trí khác nhau trong chuỗi tấn công:

1. Cấu hình phân tán theo dịch vụ

  • Ưu điểm: Nhanh gọn. Bạn chỉ cần sửa 1-2 dòng trong file config quen thuộc rồi reload daemon.
  • Hạn chế: Dễ bỏ lọt lỗ hổng. Bạn có thể giới hạn 3 lần gõ sai cho SSH. Nhưng tài khoản đó vẫn có thể bị brute-force không giới hạn thông qua giao diện Webmin, cổng FTP hoặc lệnh su ngay trên máy.

2. Tường lửa mềm Fail2ban

  • Ưu điểm: Chặn triệt để gói tin mạng rác từ bên ngoài. CPU không phải tốn tài nguyên xử lý quá trình bắt tay SSH.
  • Hạn chế: Bất lực trước mạng botnet phân tán (Distributed Brute-force). Nếu hacker dùng mạng 1.000 proxy xoay vòng, mỗi IP chỉ thử đúng 1 lần rồi đổi IP khác, Fail2ban sẽ không bao giờ chạm tới ngưỡng kích hoạt jail. Ngoài ra, Fail2ban hoàn toàn vô tác dụng nếu kẻ tấn công đã có shell nội bộ và đang brute-force mật khẩu root qua su.

3. Kiểm soát tập trung bằng PAM

  • Ưu điểm: Khóa trực tiếp định danh người dùng (user account), bất kể yêu cầu đến từ IP nào hay qua giao thức gì. PAM cho phép quy định chặt chẽ: sai 5 lần thì khóa user trong 15 phút, bắt buộc mật khẩu dài tối thiểu 12 ký tự và không được trùng tên đăng nhập.
  • Rủi ro: Can thiệp vào PAM rất nhạy cảm. Chỉ cần sai một khoảng trắng hoặc đặt nhầm thứ tự module, bạn có thể tự khóa quyền truy cập của chính mình.

Chiến lược phòng thủ theo chiều sâu

Đừng chọn một trong hai. Mô hình chuẩn cho môi trường production luôn là kết hợp song song: đặt Fail2ban ở cổng mạng ngoài để lọc bớt 95% lưu lượng quét tự động, đồng thời dùng PAM bên trong làm rào chắn cuối cùng bảo vệ tài khoản.

Các bước cấu hình PAM chi tiết: pam_faillock và pam_pwquality

Trước khi gõ bất kỳ lệnh nào bên dưới, hãy mở sẵn 2 cửa sổ SSH riêng biệt có phiên root đang hoạt động. Tuyệt đối không đóng 2 cửa sổ này cho tới khi bạn kiểm tra đăng nhập thành công ở một terminal thứ ba.

Bước 1: Cài đặt module cần thiết

Từ Ubuntu 20.04/22.04 và RHEL/CentOS 8 trở lên, pam_faillock đã thay thế hoàn toàn cho module pam_tally2 cũ vốn đã bị deprecated.

Trên Ubuntu/Debian:

sudo apt update
sudo apt install -y libpam-modules libpam-pwquality

Trên RHEL/Rocky Linux/AlmaLinux:

sudo dnf install -y pam pam-devel libpwquality

Bước 2: Cấu hình khóa tài khoản tự động với pam_faillock

Cách quản trị an toàn nhất hiện nay là cấu hình thông qua file tập trung /etc/security/faillock.conf:

sudo nano /etc/security/faillock.conf

Bỏ chú thích và thiết lập các giá trị tiêu chuẩn sau:

# Số lần nhập sai tối đa trước khi khóa
deny = 5

# Khoảng thời gian reset bộ đếm lỗi (giây)
fail_interval = 900

# Thời gian khóa tài khoản: 900 giây (15 phút)
unlock_time = 900

# Không báo rõ lý do từ chối để tránh lộ user tồn tại
silent

Tiếp theo, kích hoạt faillock trong stack xác thực của hệ thống.

Trên Ubuntu/Debian, mở file /etc/pam.d/common-auth:

sudo nano /etc/pam.d/common-auth

Khai báo pam_faillock.so bao quanh dòng kiểm tra pam_unix.so:

auth required pam_faillock.so preauth
auth [success=1 default=ignore] pam_unix.so nullok
auth [default=die] pam_faillock.so authfail
auth sufficient pam_faillock.so authsucc

Đồng thời mở /etc/pam.d/common-account và thêm dòng sau lên đầu file:

account required pam_faillock.so

Lưu ý cho RHEL/Rocky Linux: Không sửa trực tiếp file PAM thủ công. Hãy chạy lệnh sudo authselect enable-feature with-faillock rồi dùng authselect apply-changes để tránh bị ghi đè cấu hình.

Bước 3: Siết độ phức tạp mật khẩu bằng pam_pwquality

Mở file cấu hình chính sách mật khẩu tại /etc/security/pwquality.conf:

sudo nano /etc/security/pwquality.conf

Cập nhật các chỉ số:

# Độ dài tối thiểu
minlen = 12

# Bắt buộc ít nhất 1 chữ số
dcredit = -1

# Bắt buộc ít nhất 1 chữ thường
lcredit = -1

# Bắt buộc ít nhất 1 chữ hoa
ucredit = -1

# Bắt buộc ít nhất 1 ký tự đặc biệt
ocredit = -1

# Cấm đặt mật khẩu chứa username
usercheck = 1

# Cấm trùng quá 3 ký tự liên tiếp với mật khẩu cũ
maxrepeat = 3

Quy ước giá trị âm (ví dụ -1) nghĩa là điều kiện bắt buộc, khác với giá trị dương vốn chỉ tính điểm cộng trọng số khi người dùng đặt pass.

Bước 4: Tra cứu log và mở khóa tài khoản bằng lệnh faillock

Khi có sự cố nhân sự nhập sai mật khẩu quá 5 lần, tài khoản sẽ tự động chuyển sang trạng thái khóa. Bạn dùng quyền root để kiểm tra:

# Xem chi tiết các mốc thời gian và IP gửi request sai
sudo faillock --user deploy_user

Output mẫu trên terminal:

deploy_user:
When                Type  Source                                           Valid
2026-03-15 09:12:01 RHOST 192.168.1.50                                      V
2026-03-15 09:12:08 RHOST 192.168.1.50                                      V
2026-03-15 09:12:15 RHOST 192.168.1.50                                      V
2026-03-15 09:12:22 RHOST 192.168.1.50                                      V
2026-03-15 09:12:30 RHOST 192.168.1.50                                      V

Để mở khóa khẩn cấp mà không cần chờ hết 15 phút:

sudo faillock --user deploy_user --reset

Bước 5: Kiểm thử luồng hoạt động

Giữ nguyên terminal root hiện tại. Mở thêm một cửa sổ terminal mới để tiến hành test:

  1. Thực hiện lệnh ssh deploy_user@<ip_server> và cố tình nhập sai mật khẩu liên tiếp 5 lần.
  2. Đến lần thứ 6, dù bạn nhập đúng mật khẩu thật, hệ thống vẫn từ chối phiên truy cập (Permission denied).
  3. Quay lại terminal root, chạy lệnh sudo faillock --user deploy_user để xác nhận trạng thái khóa.
  4. Chạy sudo faillock --user deploy_user --reset. Lúc này, user đã có thể đăng nhập lại ngay lập tức.
Share: