You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过iptables封禁日志中每分钟请求超N次的IP地址

分钟级IP请求统计+iptables自动封禁方案

你当前的预处理逻辑存在排序缺陷:sort -n -k 1,4 按数字排序会打散同IP不同时间的日志(比如示例中119.252.76.162的21点日志被排到22点日志之后),会导致统计不准,下面是修正后的完整实现,不需要额外安装依赖,用原生awk+shell即可完成。


核心逻辑

  • 修正日志预处理排序规则,保证同IP日志按时间顺序聚合
  • 将日志中的时间戳截断到分钟粒度,按「IP+分钟」维度分组计数
  • 筛出任意一分钟请求量超过阈值的IP,跳过白名单、避免重复添加iptables规则
  • 通过crontab定时执行,实现自动检测封禁

完整脚本

先把脚本存为 /usr/local/bin/auto_ban_overload_ip.sh,按需修改开头的配置项:

#!/bin/bash
###################### 配置项 按需修改 ######################
LOG_PATH="/var/log/nginx/access.log"  # 你的访问日志路径
REQUEST_THRESHOLD=4                   # 单分钟请求数阈值,超过即封禁
WHITELIST=("127.0.0.1" "10.0.0.1")    # 白名单IP,永不封禁
BAN_LOG="/var/log/auto_ban_ip.log"    # 封禁操作日志路径
###########################################################

# 统计所有超阈值IP
BAN_IP_LIST=$(awk -v threshold="$REQUEST_THRESHOLD" '
{
    # 截掉时间戳末尾的秒级字段,保留到分钟粒度(格式:日/月/年:时:分)
    minute_tag = substr($2, 1, length($2)-3)
    stat_key = $1 "|" minute_tag
    req_count[stat_key]++
}
END {
    for (k in req_count) {
        if (req_count[k] > threshold) {
            split(k, key_arr, "|")
            # 同个IP多次超限只输出一次
            if (!is_banned[key_arr[1]]) {
                is_banned[key_arr[1]] = 1
                print key_arr[1]
            }
        }
    }
}
' <(awk '{print $1, $4}' "$LOG_PATH" | sed "s/\[//g" | sort -k1,1 -k2,2))

# 遍历IP执行封禁
for ip in $BAN_IP_LIST; do
    # 跳过白名单
    in_white=0
    for wip in "${WHITELIST[@]}"; do
        if [ "$ip" = "$wip" ]; then
            in_white=1
            break
        fi
    done
    if [ $in_white -eq 1 ]; then
        continue
    fi

    # 检查是否已经存在封禁规则,避免重复添加
    iptables -C INPUT -s "$ip" -j DROP 2>/dev/null
    if [ $? -ne 0 ]; then
        iptables -I INPUT -s "$ip" -j DROP
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 封禁IP $ip,触发条件:单分钟请求数超过$REQUEST_THRESHOLD" >> "$BAN_LOG"
    fi
done

给脚本加执行权限:

chmod +x /usr/local/bin/auto_ban_overload_ip.sh

配置定时运行

通过crontab配置每分钟执行一次脚本,实现实时检测封禁:

# 编辑crontab
crontab -e
# 写入以下规则后保存退出
* * * * * /usr/local/bin/auto_ban_overload_ip.sh

效果验证

用你给出的示例日志跑统计逻辑:

  • 10.200.3.120 在20/May/2021:21:05分钟内共有5条请求,超过阈值4
  • 119.252.76.162 在20/May/2021:22:05分钟内共有5条请求,超过阈值4
    两个IP都会被准确识别并封禁,符合预期。

可选优化

  • 如果需要自动解封,可以搭配ipset管理封禁IP,给规则加过期时间,比直接写iptables规则性能更好
  • 如果日志格式不是默认Nginx/Apache格式,只需要调整预处理阶段提取IP、时间字段的awk列号即可,核心统计逻辑不需要修改
  • 阈值请根据业务正常请求量设置,避免阈值过低误封正常用户

内容的提问来源于stack exchange,提问作者Ali Abdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 18:16:00