应使用pam_faillock实现账户级锁定并配合fail2ban实现ip级封禁:在/etc/pam.d/sshd中配置preauth/authfail/authsucc三行规则,使用户5分钟内连续失败3次即锁定10分钟;同时启用fail2ban监听日志自动封禁ip,避免手写脚本导致的格式兼容、并发异常与绕过风险。

Linux系统中,多路径身份验证失败后自动加入黑名单,需结合PAM模块(如pam_faillock)与自定义脚本协同实现。单纯靠脚本轮询日志做IP封禁,既不实时也不安全;真正可靠的方式是依托系统认证框架,在认证环节就触发锁定逻辑。
使用pam_faillock实现账户级失败锁定
pam_faillock是RHEL/CentOS 7+、Ubuntu 20.04+等主流发行版默认支持的PAM模块,可对用户连续失败登录进行计数并临时锁定账户(非IP)。它不依赖外部脚本,原生集成于sshd、login等服务。
- 编辑/etc/pam.d/sshd,在顶部添加两行:
auth [default=ignore] pam_faillock.so preauth silent deny=3 unlock_time=600
auth [default=die] pam_faillock.so authfail deny=3 unlock_time=600
- 再在文件末尾添加一行(记录成功登录,重置计数):
auth [default=ok] pam_faillock.so authsucc
- 配置生效后,同一用户5分钟内连续失败3次,该账户将被锁定10分钟(600秒),期间任何认证方式(密码、keyboard-interactive)均拒绝
- 锁定状态可通过faillock --user username查看,手动解锁用faillock --user username --reset
配合fail2ban实现IP级自动封禁
若需基于源IP封禁(例如防止暴力破解多个账号),推荐使用fail2ban——它监听认证日志(/var/log/secure或auth.log),匹配失败模式后调用iptables/nftables封禁IP。
- 安装后启用sshd过滤器:systemctl enable --now fail2ban
- 检查默认jail:fail2ban-client status sshd
- 如需调整策略(如3次失败封1小时),编辑/etc/fail2ban/jail.local:
[sshd]
enabled = true
maxretry = 3
bantime = 3600
findtime = 600
- fail2ban会自动识别pam_faillock记录的日志(含“pam_faillock”关键字),也兼容OpenSSH原生日志,无需额外脚本解析
- 封禁规则由backend(iptables/nftables/systemd)自动部署,解封时间到即自动恢复
不建议手写轮询脚本的原因
直接用shell脚本tail -f日志+awk+iptables,看似简单,实则存在多个隐患:
- 日志格式随OpenSSH/PAM版本变化,正则易失效(如新版本日志含microsecond时间戳、JSON字段)
- 并发登录时,脚本可能漏判或重复封禁;无事务机制,异常退出导致IP残留封锁
- 无法区分真实攻击与误操作(如用户输错密码后切账号重试),缺乏白名单、信任网络等策略支持
- 绕过PAM直接调用sshd_auth(如密钥登录成功但后续交互式认证失败)时,日志不触发,脚本完全失效
增强场景:多路径认证下的特殊处理
若“多路径”指同时启用密码+Google Authenticator(PAM模块pam_google_authenticator)或YubiKey(pam_yubico),需注意:
- pam_faillock默认只统计auth [default=die]阶段失败,因此必须确保所有认证模块(包括OTP模块)都位于pam_faillock authfail行之后
- 推荐顺序:pam_faillock preauth → 密码模块 → OTP模块 → pam_faillock authfail → pam_faillock authsucc
- 这样无论密码错、OTP错、还是两者都错,只要最终认证失败,都会计入失败计数
- 避免将OTP模块放在pam_faillock之前,否则OTP失败不会触发锁定,削弱防护效果










