开发工具

以下是一个用于自动屏蔽频繁访问网站的恶意IP的Shell脚本,通过分析Web服务器(如Nginx/Apache)的访问日志并结合iptables实现实时防护:

脚本功能

1、监控Web访问日志,检测短时间内高频访问的IP
2、自动将恶意IP加入iptables黑名单
3、支持自定义检测阈值、封锁时间和日志路径
4、避免重复封锁IP,记录操作日志

脚本代码

#!/bin/bash
# 自动屏蔽高频访问IP的防护脚本

# 配置参数
LOG_FILE="/var/log/nginx/access.log"  # 访问日志路径
THRESHOLD=100                         # 触发封锁的请求次数阈值
TIME_WINDOW=60                        # 检测时间窗口(秒)
BAN_TIME=3600                         # 封锁时长(秒)
WHITELIST=("127.0.0.1" "192.168.1.1") # IP白名单
FIREWALL_CMD="iptables"               # 防火墙命令(可选ipset)

# 日志与临时文件
LOG_DIR="/var/log/iptables_blocker"
BLOCK_LOG="$LOG_DIR/blocked_ips.log"
TMP_IP_LIST="/tmp/block_ips.txt"

# 创建日志目录
mkdir -p "$LOG_DIR"

# 函数:检查是否为有效IPv4地址
is_valid_ip() {
    local ip=$1
    local stat=1
    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        IFS='.' read -ra ip_parts <<< "$ip"
        [[ ${ip_parts[0]} -le 255 && ${ip_parts[1]} -le 255 && \
           ${ip_parts[2]} -le 255 && ${ip_parts[3]} -le 255 ]]
        stat=$?
    fi
    return $stat
}

# 函数:检查IP是否在白名单
is_whitelisted() {
    local ip=$1
    for allowed_ip in "${WHITELIST[@]}"; do
        [[ "$ip" == "$allowed_ip" ]] && return 0
    done
    return 1
}

# 主检测逻辑
detect_and_block() {
    # 获取当前时间(时间戳格式)
    current_time=$(date +%s)
    
    # 分析最近TIME_WINDOW秒内的日志,提取访问量超阈值的IP
    awk -v window="$TIME_WINDOW" -v now="$current_time" '
    {
        # 解析日志时间(假设日志时间格式为[05/Oct/2023:14:30:22 +0800])
        gsub(/\[/, "", $4);
        log_time = substr($4, 1, 20);
        cmd = "date -d \"" log_time "\" +%s";
        cmd | getline timestamp;
        close(cmd);
        
        if (now - timestamp <= window) {
            print $1;
        }
    }' "$LOG_FILE" | sort | uniq -c | awk -v threshold="$THRESHOLD" '$1 > threshold {print $2}' > "$TMP_IP_LIST"

    # 处理每个待屏蔽IP
    while read ip; do
        if is_valid_ip "$ip" && ! is_whitelisted "$ip"; then
            # 检查是否已封锁
            if ! $FIREWALL_CMD -C INPUT -s "$ip" -j DROP 2>/dev/null; then
                # 添加iptables规则
                $FIREWALL_CMD -A INPUT -s "$ip" -j DROP
                echo "[$(date '+%Y-%m-%d %H:%M:%S')] 屏蔽IP: $ip" >> "$BLOCK_LOG"
                
                # 设置自动解封(可选)
                echo "$FIREWALL_CMD -D INPUT -s "$ip" -j DROP" | at now + "$BAN_TIME" minutes 2>/dev/null
            fi
        fi
    done < "$TMP_IP_LIST"
}

# 执行检测
detect_and_block

# 清理临时文件
rm -f "$TMP_IP_LIST"

使用说明

1、配置参数

修改 LOG_FILE 为你的Web服务器访问日志路径(支持Nginx/Apache)

调整 THRESHOLD 和 TIME_WINDOW 定义触发条件(如60秒内100次请求)

WHITELIST 中添加需豁免的IP(如管理服务器IP)


2、脚本权限

chmod +x ip_blocker.sh
sudo ./ip_blocker.sh  # 需要root权限运行


3、定时任务

通过crontab每5分钟执行一次:

*/5 * * * * root /path/to/ip_blocker.sh


4、查看封锁记录

tail -f /var/log/iptables_blocker/blocked_ips.log



扩展功能

1. 使用ipset提升性能(应对大量IP)

# 创建ipset集合
ipset create block_list hash:ip timeout 3600

# 修改脚本中的防火墙规则
FIREWALL_CMD="iptables -m set --match-set block_list src"
ipset add block_list $ip


2. 邮件/钉钉告警

# 在屏蔽IP时发送通知
echo "检测到恶意IP: $ip,已自动封锁" | \
mail -s "安全告警" admin@example.com

# 钉钉机器人通知(需替换WEBHOOK_URL)
WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=xxx"
curl -s "$WEBHOOK_URL" -H 'Content-Type: application/json' -d "{
    'msgtype': 'text',
    'text': {'content': '封锁恶意IP: $ip'}
}"


3. 自动解封

# 使用at命令在BAN_TIME分钟后自动解封
echo "iptables -D INPUT -s $ip -j DROP" | at now + "$BAN_TIME" minutes



注意事项

1、日志格式适配

脚本假设日志时间格式为 [05/Oct/2023:14:30:22 +0800],如格式不同需调整awk解析逻辑。


2、性能优化

对于高流量网站,建议使用 ipset 或 fail2ban 替代直接操作iptables。


3、误封风险

阈值设置需结合业务场景,避免误封CDN或搜索引擎IP。


4、防火墙规则持久化

iptables规则重启后会丢失,需使用 iptables-save 保存:

iptables-save > /etc/iptables/rules.v4


5、法律合规

确保符合当地法律法规,禁止未授权扫描和封锁。

通过此脚本,您可以有效防御CC攻击、爬虫高频请求等恶意行为,保障Web服务的稳定性。建议结合其他安全措施(如WAF)构建多层防护体系。