生产环境不建议直接用OpenSSH实现动态黑名单,应依赖fail2ban或自定义脚本联动日志与防火墙。fail2ban是首选方案,通过监控auth.log/secure,自动触发iptables封禁;无fail2ban时可用shell脚本+cron定时扫描日志并封禁异常IP。

生产环境不建议直接用 OpenSSH 自身实现“动态黑名单”,因为它没有内置的实时 IP 封禁机制。真正的自动化封禁必须依赖外部工具与 SSH 日志联动,形成“检测→分析→阻断→清理”闭环。核心思路是:让 faillog / auth.log 中的失败登录行为触发防火墙规则变更,而非修改 sshd_config 或依赖 SSH 模块扩展。
一、基于 fail2ban 的轻量级自动封禁(推荐首选)
fail2ban 是生产环境最成熟、低侵入、可审计的方案,支持 Ubuntu/CentOS/Rocky/openEuler 等主流系统,无需重启 sshd 即可生效。
- 安装并启用服务:
sudo apt install fail2ban -y(Ubuntu/Debian)或sudo dnf install fail2ban -y(RHEL系)
启动后默认监听/var/log/auth.log(Debian系)或/var/log/secure(RHEL系) - 创建自定义 jail 配置(避免覆盖默认模板):
新建/etc/fail2ban/jail.local,写入:
[sshd] enabled = true filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 1h findtime = 10m action = iptables[name=SSH, port=ssh, protocol=tcp]
- 关键参数说明:
maxretry:10 分钟内(findtime)连续失败 3 次即触发;
bantime:封禁 1 小时(支持1d、4w等格式);
action 可替换为firewallcmd-ipset(适配 firewalld)或iptables-allports(全端口封禁) - 验证与加载:
sudo fail2ban-client status sshd查看当前封禁数sudo fail2ban-client set sshd unbanip 192.168.1.100手动解封(调试必备)
二、无 fail2ban 时的 shell 脚本方案(应急/嵌入式场景)
适用于资源受限或无法安装额外包的环境(如 Buildroot 嵌入式系统),需配合 cron 定期扫描日志。
- 脚本逻辑要点:
提取最近 5 分钟内失败登录的 IP → 过滤掉内网地址和已封禁项 → 写入 iptables 规则 → 记录到/var/log/sshd-ban.log - 示例片段(保存为
/usr/local/bin/sshd-ban.sh):
#!/bin/bash
LOG="/var/log/auth.log"
BANLIST="/tmp/sshd-banned.tmp"
NOW=$(date -d '5 minutes ago' '+%b %d %H:%M')
# 提取异常IP(仅匹配"Failed password"且时间在范围内)
grep "Failed password" "$LOG" | awk -v d="$NOW" '$0 > d {print $11}' | \
sed 's/[^0-9.]//g' | grep -E '^[0-9]{1,3}\.[0-9]{1,3}' | \
sort -u | grep -vE '^(127\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)' > "$BANLIST"
while read ip; do
if ! iptables -C INPUT -s "$ip" -j DROP 2>/dev/null; then
iptables -I INPUT -s "$ip" -j DROP
echo "$(date): BAN $ip" >> /var/log/sshd-ban.log
fi
done < "$BANLIST"- 加入定时任务:
sudo crontab -e添加:*/2 * * * * /usr/local/bin/sshd-ban.sh(每 2 分钟执行一次) - 注意:该脚本需 root 权限运行,且 iptables 规则重启后失效,建议搭配
iptables-save持久化
三、与 firewalld + ipset 高效联动(万级IP封禁场景)
当单台服务器面临高频暴力破解(如每秒数十次尝试),iptables 直接追加规则会导致性能下降。此时应改用 ipset 统一管理黑名单,firewalld 仅引用一个集合。
- 创建 ipset 黑名单集合:
sudo ipset create ssh-ban hash:ip timeout 3600(自动过期 1 小时) - 配置 firewalld 富规则引用:
sudo firewall-cmd --permanent --add-rich-rule='rule source ipset="ssh-ban" reject' - fail2ban 对应 action 修改为:
action = %(action_)s[name=SSH, bantime=<b>3600</b>, port="ssh", protocol="tcp"]
并在/etc/fail2ban/action.d/iptables-common.conf中将iptables -I替换为ipset add ssh-ban <ip> timeout 3600 - 优势:添加/删除万级 IP 几乎无延迟,规则数量恒定为 1 条
四、关键安全前提与避坑提醒
- 永远保留一个未被封禁的管理通道:升级前务必启用 Telnet 备用(监听非 23 端口)、配置串口控制台,或确保跳板机 IP 在白名单中
-
日志轮转必须开启:否则脚本或 fail2ban 可能漏扫归档日志,建议
logrotate配置保留 7 天以上 auth 日志 -
禁止封禁云厂商元数据 IP:如阿里云
100.100.100.200、AWS169.254.169.254,误封会导致实例失联 - 封禁策略要区分内外网:对内网 IP 可设更宽松阈值(如 maxretry=10),外网严格限制(maxretry=3),避免办公网段被连带误伤

















