Cả hai — mỗi chiều chặn một dạng tấn công khác nhau, dùng một chiều là có lỗ hổng.
| Khoá đếm | Chặn được | Điểm mù |
|---|---|---|
| Theo tài khoản | Dò mật khẩu một tài khoản từ botnet nhiều IP | Credential stuffing rải mỏng (mỗi account 1 lần) |
| Theo IP | Kịch bản dò từ một nguồn | Botnet, proxy xoay IP; và chặn nhầm cả văn phòng/nhà mạng đứng sau một NAT |
Thiết kế thực dụng gồm nhiều tầng chạy song song:
1. Theo tài khoản — backoff tăng dần trên số lần sai liên tiếp.
2. Theo IP — trần số lần đăng nhập thất bại trong cửa sổ thời gian, đặt đủ rộng để không chặn nhầm NAT của công ty.
3. Theo (IP, tài khoản) — cặp này bắt đúng kịch bản dò tập trung.
4. Theo ASN/subnet và toàn hệ thống — chống botnet phân tán: nếu tỉ lệ đăng nhập thất bại toàn cục vọt lên bất thường thì bật CAPTCHA cho mọi người, đây là tín hiệu duy nhất nhìn thấy được credential stuffing.
Các điểm hay sai khi cài đặt:
- Đọc IP từ X-Forwarded-For mà không tin cậy proxy → kẻ tấn công tự đặt header để né. Chỉ lấy IP do lớp proxy của mình gán.
- Bộ đếm để trong bộ nhớ tiến trình → chạy nhiều instance là vô hiệu. Dùng kho dùng chung (Redis).
- Chỉ đếm ở endpoint /login mà quên các đường vào khác: đổi mật khẩu, refresh token, gửi lại OTP, API đăng nhập cho mobile.
- Không giới hạn nên mỗi request đều chạy hash chậm → chính hàm bảo vệ mật khẩu trở thành điểm cạn tài nguyên.