Shell脚本配置SSH访问黑名单:从入门到实战的完整指南
📖 目录导读
为什么需要SSH黑名单?
SSH(安全外壳协议)作为服务器远程管理的核心工具,一直是暴力破解攻击的重点目标,攻击者通过脚本批量尝试用户名和密码,一旦成功即可控制服务器。配置IP黑名单可以将可疑IP永久或临时封禁,从源头阻断攻击。

核心痛点:
- 手动封禁效率低,无法应对分布式攻击
- 系统自带的
hosts.deny不支持动态更新 - 日志文件
/var/log/auth.log每天可能记录成千上万次失败尝试
通过Shell脚本自动化黑名单管理,能实现实时监控+自动封禁+灵活解封的三重防护。
SSH访问黑名单的核心机制
系统层面封禁工具
| 工具 | 特点 | 适用场景 |
|---|---|---|
iptables |
防火墙规则,永久生效 | 需要深度控制的场景 |
hosts.deny |
TCP Wrapper简单配置 | 快速临时封禁 |
fail2ban |
自动封禁+解封 | 生产环境首选 |
黑名单判定逻辑
一个健壮的黑名单系统应包含:
- 阈值触发:5分钟内失败3次自动封禁
- 白名单例外:管理员IP和白名单IP永不封禁
- 时间衰减:封禁时间随攻击次数递增(如1分钟→1小时→24小时)
- 源IP验证:排除内网IP和保留地址
基础脚本:用Shell实现IP黑名单
下面是一个可直接运行的Shell脚本,自动监控SSH日志并封禁恶意IP:
ssh_blacklist.sh 完整代码
#!/bin/bash
# SSH黑名单自动封禁脚本 v2.0
# 配置参数
LOG_FILE="/var/log/auth.log"
THRESHOLD=5 # 失败次数阈值
BAN_TIME=3600 # 封禁时间(秒)
WHITE_LIST=("192.168.1.100" "10.0.0.0/8")
# 1. 提取失败IP并统计
FAILED_IPS=$(grep "Failed password" $LOG_FILE | awk '{print $(NF-3)}' | sort | uniq -c | awk -v th=$THRESHOLD '$1 > th {print $2}')
# 2. 封禁IP
for IP in $FAILED_IPS; do
# 检查白名单
IN_WHITE=0
for WHITE in "${WHITE_LIST[@]}"; do
if [[ $IP =~ $WHITE ]]; then
IN_WHITE=1
break
fi
done
[ $IN_WHITE -eq 1 ] && continue
# 检查是否已封禁
if ! iptables -C INPUT -s $IP -j DROP 2>/dev/null; then
iptables -A INPUT -s $IP -j DROP
echo "[$(date)] 封禁IP: $IP" >> /var/log/ssh_blacklist.log
fi
done
# 3. 自动解封过期IP
CURRENT_TIME=$(date +%s)
iptables -L INPUT -n --line-numbers | grep DROP | while read line; do
IP=$(echo $line | awk '{print $4}')
if [[ -n $(grep "封禁IP: $IP" /var/log/ssh_blacklist.log) ]]; then
BAN_START=$(grep "封禁IP: $IP" /var/log/ssh_blacklist.log | tail -1 | grep -oP '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}')
BAN_STAMP=$(date -d "$BAN_START" +%s)
DIFF=$((CURRENT_TIME - BAN_STAMP))
if [ $DIFF -ge $BAN_TIME ]; then
iptables -D INPUT -s $IP -j DROP
echo "[$(date)] 解封IP: $IP" >> /var/log/ssh_blacklist.log
fi
fi
done
部署方法
chmod +x ssh_blacklist.sh # 加入crontab每5分钟执行 crontab -e */5 * * * * /path/to/ssh_blacklist.sh
进阶方案:结合fail2ban动态管理
虽然纯Shell脚本可工作,但生产环境推荐使用成熟的fail2ban,它本质上也是用Shell + Python实现,但提供了更完善的机制。
安装与配置
# 安装 apt install fail2ban -y # Debian/Ubuntu yum install fail2ban -y # CentOS/RHEL # 配置SSH防护 cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local vim /etc/fail2ban/jail.local
关键配置项
[sshd] enabled = true port = 22 filter = sshd logpath = /var/log/auth.log maxretry = 5 # 5次失败触发 bantime = 3600 # 封禁1小时 findtime = 600 # 10分钟内统计 # 增加白名单 ignoreip = 127.0.0.1/8 192.168.1.0/24
Shell脚本增强fail2ban
通过Shell脚本可以扩展fail2ban能力:
#!/bin/bash # 动态添加恶意IP到fail2ban数据库 fail2ban-client set sshd banip 192.168.1.50 # 查看封禁状态 fail2ban-client status sshd # 手动解封 fail2ban-client set sshd unbanip 192.168.1.50
安全最佳实践与常见陷阱
✅ 一定要做
- 双重验证:配置SSH密钥登录 + 黑名单,记得在
/etc/ssh/sshd_config中设置PasswordAuthentication no - 保留管理通道:在黑名单脚本中硬编码管理IP,或通过独立IPMI/iLO访问
- 日志监控:将封禁日志发送到中央日志服务器
- 定期清理:设置
iptables规则最大数量上限(如1000条),防止规则表溢出
❌ 不要做
- 只封禁不解封:导致合法用户永久被锁
- 误封CDN/代理IP:某些CDN节点IP会动态变化,建议排除
Cloudflare等知名IP段 - 忽略IPv6:攻击者可能通过IPv6绕过
常见陷阱案例
问题:脚本执行后SSH完全无法连接
原因:白名单配置错误,本机IP未加入白名单
解决:在脚本开头加入WHITE_LIST+=("$(curl -s ifconfig.me)")自动获取本机公网IP
常见问题问答(FAQ)
Q1:如何查看当前被封禁的IP列表?
A:使用iptables -L INPUT -n | grep DROP或fail2ban-client status sshd查看。
Q2:封禁IP后攻击者换IP怎么办?
A:需结合fail2ban的recidive监狱,对重复攻击者封禁时间指数增长(如1小时→24小时→永久)。
Q3:我的服务器没有iptables怎么办?
A:可使用ufw(Ubuntu)或firewalld(CentOS):
ufw deny from 192.168.1.50 to any port 22
Q4:Shell脚本和fail2ban选哪个?
A:小型环境(1-3台服务器)用Shell脚本+ cron即可;大型环境(超过10台)或需要集中管理时用fail2ban + 日志分析工具(如Elasticsearch)。
Q5:如何防止误封自己?
A:在脚本中加入SSH连接测试:
# 封禁前先测试本机能否连接SSH
if ssh -o ConnectTimeout=5 localhost 'echo OK'; then
# 执行封禁命令
fi
Q6:黑名单规则是否影响SSH性能?
A:iptables规则匹配对系统影响极小,但规则超过1000条可能增加延迟,建议使用ipset创建集合提升效率:
ipset create ssh_blacklist hash:ip iptables -A INPUT -m set --match-set ssh_blacklist src -j DROP
通过本文的Shell脚本方案,你可以快速构建一个自动化的SSH黑名单防御系统。没有绝对的安全,但至少要让攻击者“成本高于收益”,建议每月审查一次黑名单日志,结合地理位置分析(如GeoIP)优化封禁策略。