暴力屏蔽80访问失败的用户
暴力屏蔽80访问失败的用户:从iptables到智能防护
📌 文章导读
网站经常被恶意扫描、暴力破解或CC攻击?本文分享一个简单粗暴的防护脚本:通过分析Apache错误日志,自动将访问失败次数过多的IP加入iptables黑名单。同时,我们也会探讨这种方案的优缺点,以及更优雅的替代方案。
💡 作者注:这个脚本确实很暴力——直接封IP,可能会误伤正常用户(比如输错密码的访客)。建议在生产环境中配合程序层的友好提示使用,提升真实用户体验。
📜 一、原始脚本解析
1.1 脚本代码
#!/bin/bash # 功能:分析Apache错误日志,自动封禁失败次数过多的IP # 作者:GuoYabin # 读取最后100行错误日志,提取IP,统计出现次数,取最高频的IP error=`/usr/bin/tail -n100 /usr/local/apache2/logs/error_log |awk -F ' ' '{print $8}' |awk -F ']' '{print $1}' |sort -rn |uniq -c |sort -r |head -n1` # 提取失败次数和IP地址 errnum=`/bin/echo $error |awk -F ' ' '{print $1}'` # 如果失败次数大于30,则封禁该IP if [ $errnum -gt 30 ];then errip=`/bin/echo $error | awk -F ' ' '{print $2}'` # 清空所有iptables规则(⚠️ 危险操作!) /sbin/iptables -F # 添加封禁规则 /sbin/iptables -A INPUT -s $errip -p tcp --dport 80 -j DROP fi
1.2 逐行解析
| 命令/部分 | 作用 | 潜在问题 |
|---|---|---|
tail -n100 error_log |
读取最后100行错误日志 | 100行样本可能太小,易误判 |
awk -F ' ' '{print $8}' |
提取第8列(假设IP在第8列) | 日志格式不同时列位置会变 |
sort | uniq -c | sort -r |
统计IP出现次数并排序 | 标准统计方法,没问题 |
iptables -F |
清空所有防火墙规则! | 会删除已有的安全规则,极其危险 |
判断条件 -gt 30 |
失败次数超过30则封禁 | 阈值硬编码,不灵活 |
⚠️ 二、原始脚本的主要问题
🚨 1. iptables -F:灾难性的操作
iptables -F 会清空所有防火墙规则,包括SSH放行规则、已有防护规则等。如果服务器是远程连接,可能导致自己把自己封在外面,无法再登录!
🔴 2. 只处理一个IP
脚本只处理出现次数最多的一个IP,如果有多个恶意IP同时攻击,其他IP不会被封。
🔴 3. 日志格式依赖
awk '{print $8}' 假设IP地址在日志的第8列,但不同的Apache配置、日志格式会导致列位置不同,脚本不具备通用性。
🔴 4. 样本量太小
只分析最后100行日志,如果正常用户偶尔输错密码,也可能被误封。
🛠️ 三、优化版脚本
针对以上问题,我重新编写了一个更安全、更灵活的版本:
#!/bin/bash # ============================================ # 智能Apache防暴力攻击脚本 v2.0 # 功能:分析错误日志,自动封禁异常IP # 特性:多IP处理、防误封、规则追加、日志记录 # ============================================ # 配置参数 LOG_FILE="/usr/local/apache2/logs/error_log" # 日志路径 LINES=500 # 分析的日志行数 THRESHOLD=30 # 失败次数阈值 BANNED_LOG="/var/log/ban_ip.log" # 封禁记录日志 WHITE_LIST="192.168.1. 10.0.0. 127.0.0.1" # 白名单IP前缀 # 检查日志文件是否存在 if [ ! -f $LOG_FILE ]; then echo "错误: 日志文件 $LOG_FILE 不存在" exit 1 fi # 提取异常IP(失败次数超过阈值的IP列表) bad_ips=$(tail -n $LINES $LOG_FILE | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort | uniq -c | sort -rn | awk -v threshold=$THRESHOLD '$1 > threshold {print $2}') # 如果没有异常IP,直接退出 if [ -z "$bad_ips" ]; then exit 0 fi # 处理每个异常IP for ip in $bad_ips; do # 检查是否在白名单中 in_whitelist=0 for white in $WHITE_LIST; do if [[ $ip == $white* ]]; then in_whitelist=1 break fi done if [ $in_whitelist -eq 1 ]; then echo "跳过白名单IP: $ip" continue fi # 检查IP是否已经被封禁 iptables -C INPUT -s $ip -p tcp --dport 80 -j DROP 2>/dev/null if [ $? -eq 0 ]; then echo "IP $ip 已存在封禁规则,跳过" continue fi # 添加封禁规则(追加方式,不清空现有规则) /sbin/iptables -A INPUT -s $ip -p tcp --dport 80 -j DROP # 记录封禁日志 echo "$(date '+%Y-%m-%d %H:%M:%S') 封禁IP: $ip (失败次数超过$THRESHOLD)" >> $BANNED_LOG done # 保存iptables规则(防止重启后丢失) if command -v iptables-save &>/dev/null; then iptables-save > /etc/sysconfig/iptables 2>/dev/null fi exit 0
🔍 四、优化点详解
4.1 正则提取IP(通用性强)
# 使用正则表达式匹配IPv4地址,不依赖列位置
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
4.2 多IP同时处理
# 一次性提取所有超过阈值的IP,用循环处理
bad_ips=$(... | awk '$1 > threshold {print $2}')
for ip in $bad_ips; do
# 逐个处理
done
4.3 白名单机制
# 防止误封内网IP、公司出口IP等
WHITE_LIST="192.168.1. 10.0.0. 127.0.0.1"
# 检查IP是否以白名单前缀开头
4.4 规则检查与追加
# 检查IP是否已被封禁,避免重复添加 iptables -C INPUT -s $ip -p tcp --dport 80 -j DROP 2>/dev/null # 追加规则(-A),不清空现有规则 iptables -A INPUT -s $ip -p tcp --dport 80 -j DROP
4.5 日志记录
# 记录封禁时间和IP,方便后续审计和解封
echo "$(date) 封禁IP: $ip" >> /var/log/ban_ip.log
⚙️ 五、部署与使用
5.1 保存脚本
# 保存为 /usr/local/bin/ban_abusive_ips.sh
chmod +x /usr/local/bin/ban_abusive_ips.sh
5.2 添加到计划任务
# 每5分钟执行一次
*/5 * * * * /usr/local/bin/ban_abusive_ips.sh > /dev/null 2>&1
5.3 查看封禁记录
cat /var/log/ban_ip.log
5.4 手动解封IP
# 删除指定IP的封禁规则 iptables -D INPUT -s 恶意IP -p tcp --dport 80 -j DROP # 保存规则 iptables-save > /etc/sysconfig/iptables
🔄 六、更优雅的替代方案
iptables封IP虽然有效,但确实比较暴力。以下是一些更优雅的防护方案:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 程序层验证码 | 用户体验好,区分真实用户和机器 | 需要修改代码 | 登录页面、表单提交 |
| fail2ban | 专业工具,支持多种服务,规则灵活 | 需要额外安装配置 | 生产环境全面防护 |
| nginx限流模块 | 限制请求频率,不封IP | 只适用于nginx | Web服务器防护 |
| CDN/WAF | 云端防护,无需维护服务器 | 可能产生费用 | 大中型网站 |
📊 七、fail2ban配置示例(推荐)
如果你希望更专业的防护方案,强烈推荐使用fail2ban。以下是针对Apache的配置示例:
# 安装fail2ban yum install -y epel-release yum install -y fail2ban # 创建本地配置文件 cat > /etc/fail2ban/jail.local << 'EOF' [DEFAULT] ignoreip = 127.0.0.1/8 192.168.1.0/24 10.0.0.0/8 # 白名单 bantime = 3600 # 封禁时间(秒) findtime = 600 # 统计时间窗口(秒) maxretry = 30 # 最大失败次数 [apache-auth] enabled = true logpath = /usr/local/apache2/logs/error_log EOF # 启动fail2ban systemctl start fail2ban systemctl enable fail2ban # 查看封禁状态 fail2ban-client status apache-auth
📝 八、总结
原始脚本虽然简单粗暴,但iptables -F的风险太大,不适合生产环境。本文提供了:
- ✅ 一个更安全的优化版脚本(多IP、白名单、日志记录)
- ✅ 多种防护方案的对比分析
- ✅ fail2ban的专业配置示例
最后再次强调:程序层的友好提示(如验证码)比暴力封IP更能提升真实用户体验。建议组合使用多种防护手段,既保证安全,又不误伤真实用户。
—— 如果你有更好的防护方案,欢迎在评论区分享交流~

浙公网安备 33010602011771号