暴力屏蔽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更能提升真实用户体验。建议组合使用多种防护手段,既保证安全,又不误伤真实用户。


—— 如果你有更好的防护方案,欢迎在评论区分享交流~

posted @ 2017-07-21 10:59  一起走过的路  阅读(176)  评论(0)    收藏  举报