
shell 脚本-定时封禁高频接口IP
#!/bin/bash
# =============================================================================
# auth:24/07/2025 by Oldhan
#
# sms_denyip.sh
#
# 功能:
# 针对多个 access_*.log(app/mil/food/ml等)文件,筛选 URI 包含某个接口(例:sms/getVerifyCode)
# 且状态码为 200、出现次数 > THRESHOLD 的 IP,写入各自的 blocksip_*.conf
# 已存在的不重复写入,只有在新增封禁 IP 时才重载 nginx
# 并将执行日志追加到 /data/sh/nginx/sms_denyip.sh
#
# 用法:
# chmod +x /data/sh/nginx/sms_denyip.sh
# 每隔15分钟由 crontab 调用:*/15 * * * * bash /data/sh/nginx/sms_denyip.sh
# =============================================================================
set -euo pipefail
LOG_EXEC="/data/sh/nginx/sms_denyip.log"
dirlog="$(dirname "$LOG_EXEC")"
if [ ! -d "$dirlog" ]; then
echo "[`date '+%Y-%m-%d %H:%M:%S'`] 脚本执行日志目录 $dirlog 不存在,正在创建…"
mkdir -p "$dirlog"
fi
# 把 stdout/stderr 都追加到日志
exec >>"$LOG_EXEC" 2>&1
echo "==================== 启动脚本 $(date '+%Y-%m-%d %H:%M:%S') ===================="
THRESHOLD=5
declare -A LOG_MAP=(
["/data/nginx-logs/access_api.log"]="/usr/local/nginx/conf/ip/blocksip_api.conf"
["/data/nginx-logs/access_mil.log"]="/usr/local/nginx/conf/ip/blocksip_mil.conf"
["/data/nginx-logs/access_food.log"]="/usr/local/nginx/conf/ip/blocksip_food.conf"
["/data/nginx-logs/access_ml.log"]="/usr/local/nginx/conf/ip/blocksip_ml.conf"
)
NGINX_CTL="nginx -s reload"
# 全局标记:是否有新增封禁
new_added=0
for LOGFILE in "${!LOG_MAP[@]}"; do
BLOCKFILE="${LOG_MAP[$LOGFILE]}"
dir="$(dirname "$BLOCKFILE")"
if [ ! -d "$dir" ]; then
echo "[`date '+%Y-%m-%d %H:%M:%S'`] 目录 $dir 不存在,正在创建…"
mkdir -p "$dir"
fi
if [ ! -f "$BLOCKFILE" ]; then
echo "[`date '+%Y-%m-%d %H:%M:%S'`] 文件 $BLOCKFILE 不存在,正在创建…"
touch "$BLOCKFILE"
fi
mapfile -t IP_LIST < <(
awk '/sms\/getVerifyCode/ && $12 == 200 { print $1 }' "$LOGFILE" \
| sort \
| uniq -c \
| sort -nr \
| awk -v th="$THRESHOLD" '$1 >= th { print $2 }'
)
if [ "${#IP_LIST[@]}" -eq 0 ]; then
echo "[`date '+%Y-%m-%d %H:%M:%S'`] $LOGFILE: 未发现超过 ${THRESHOLD} 次的 IP,跳过"
continue
fi
echo "[`date '+%Y-%m-%d %H:%M:%S'`] $LOGFILE: 找到 ${#IP_LIST[@]} 个候选 IP"
for IP in "${IP_LIST[@]}"; do
[[ -z "$IP" ]] && continue
if ! grep -qE "^\s*deny\s+${IP};" "$BLOCKFILE"; then
echo "deny ${IP};" >> "$BLOCKFILE"
echo "[`date '+%Y-%m-%d %H:%M:%S'`] 添加封禁 IP ${IP} 到 $(basename "$BLOCKFILE")"
new_added=1
fi
done
done
if [ "$new_added" -eq 1 ]; then
echo "[`date '+%Y-%m-%d %H:%M:%S'`] 有新 IP 被封禁,正在重载 nginx 配置…"
$NGINX_CTL
else
echo "[`date '+%Y-%m-%d %H:%M:%S'`] 无新增封禁 IP,跳过 nginx 重载"
fi
echo "==================== 脚本结束 $(date '+%Y-%m-%d %H:%M:%S') ===================="
exit 0
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Oldhan's World
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果