#!/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