#!/bin/bash # 配置区域 LOG_FILE="******************************" # Nginx访问日志路径 ALIYUN_REGION="cn-hangzhou" # 阿里云区域ID ALIYUN_SECURITY_GROUP_ID="sg-********" # 安全组ID ALIYUN_ACCESS_KEY="***************" # 阿里云AccessKey ALIYUN_SECRET_KEY="***************" # 阿里云SecretKey MAX_ANALYZE_LINES=4000 # 分析日志行数 TOP_IP_COUNT=6 # 取访问量前几名IP # 临时文件 TMP_IP_FILE="/tmp/top_aliyun_ips.txt" TMP_COUNTRY_FILE="/tmp/aliyun_ip_country.txt" # 日志设置 LOG_FILE_PATH="/var/log/aliyun_ip_blocker.log" # 获取当前时间 DATE=$(date +"%Y-%m-%d %H:%M:%S") # 日志函数 log() { local level=$1 local message=$2 local color_code="" case $level in "INFO") color_code="\033[32m" ;; # 绿色 "WARN") color_code="\033[33m" ;; # 黄色 "ERROR") color_code="\033[31m" ;; # 红色 *) color_code="\033[0m" ;; esac local log_entry="[$DATE][$level] $message" echo -e "${color_code}${log_entry}\033[0m" | tee -a $LOG_FILE_PATH } # 检查依赖 check_dependencies() { local missing=0 if ! command -v aliyun &> /dev/null; then log "ERROR" "阿里云CLI工具未安装,请先执行: curl -sSL https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz | tar -xz -C /usr/local/bin && mv /usr/local/bin/aliyun-linux-amd64 /usr/local/bin/aliyun" missing=1 fi if ! command -v jq &> /dev/null; then log "ERROR" "jq工具未安装,请先执行: apt-get install -y jq 或 yum install -y jq" missing=1 fi [ $missing -eq 1 ] && exit 1 log "INFO" "√ 所有依赖检查通过" } # 配置阿里云CLI setup_aliyun_cli() { export ALIBABACLOUD_ACCESS_KEY_ID=$ALIYUN_ACCESS_KEY export ALIBABACLOUD_ACCESS_KEY_SECRET=$ALIYUN_SECRET_KEY aliyun configure set \ --region $ALIYUN_REGION \ --access-key-id $ALIYUN_ACCESS_KEY \ --access-key-secret $ALIYUN_SECRET_KEY \ --mode AK log "INFO" "√ 阿里云CLI配置完成" } # 分析日志获取恶意IP analyze_logs() { log "INFO" "➤ 开始分析最近${MAX_ANALYZE_LINES}条访问日志..." tail -n $MAX_ANALYZE_LINES $LOG_FILE | \ awk '{print $1}' | \ sort | \ uniq -c | \ sort -nr | \ head -n $TOP_IP_COUNT > $TMP_IP_FILE if [ ! -s "$TMP_IP_FILE" ]; then log "ERROR" "无法从日志中提取IP地址" exit 1 fi log "INFO" "√ 获取到访问量前${TOP_IP_COUNT}的IP:" column -t $TMP_IP_FILE | while read line; do log "INFO" " $line" done } # 查询IP地理位置 check_ip_location() { log "INFO" "➤ 开始分析IP地理位置..." while read -r line; do count=$(echo "$line" | awk '{print $1}') ip=$(echo "$line" | awk '{print $2}') # 跳过本地IP if [[ "$ip" == 127.0.0.* ]] || [[ "$ip" == 192.168.* ]] || [[ "$ip" == 10.* ]]; then log "WARN" "⚠️ 跳过本地IP: $ip (访问次数: $count)" continue fi log "INFO" "🔍 正在查询 $ip (访问次数: $count)..." country=$(curl -m 5 -s "http://ip-api.com/line/$ip?fields=countryCode") if [ -z "$country" ]; then log "WARN" "无法确定 $ip 的地理位置,默认视为境外IP" country="XX" fi echo "$ip $country $count" >> $TMP_COUNTRY_FILE if [ "$country" != "CN" ]; then log "WARN" "‼️ 检测到非中国IP: $ip (国家: $country, 访问次数: $count)" block_ip $ip $country $count else log "INFO" "✓ 中国IP: $ip (访问次数: $count)" fi sleep 1.3 done < $TMP_IP_FILE } # 屏蔽IP到阿里云安全组 block_ip() { local ip=$1 local country=$2 local count=$3 # 检查是否已存在该规则 existing_rule=$(aliyun ecs DescribeSecurityGroupAttribute \ --RegionId $ALIYUN_REGION \ --SecurityGroupId $ALIYUN_SECURITY_GROUP_ID \ --Direction ingress | \ jq -r ".Permissions.Permission[] | select(.SourceCidrIp == \"$ip/32\")") if [ -n "$existing_rule" ]; then log "WARN" "⏩ 安全组中已存在 $ip 的屏蔽规则,跳过添加" return fi # 添加安全组规则 log "INFO" "🛡️ 正在将 $ip 添加到安全组屏蔽规则..." aliyun ecs AuthorizeSecurityGroup \ --RegionId $ALIYUN_REGION \ --SecurityGroupId $ALIYUN_SECURITY_GROUP_ID \ --IpProtocol tcp \ --PortRange "1/65535" \ --SourceCidrIp "$ip/32" \ --Policy drop \ --Priority 100 \ --Description "Blocked by script: $country, $count requests" \ --NicType internet if [ $? -eq 0 ]; then log "INFO" "✅ 成功屏蔽IP: $ip (国家: $country)" else log "ERROR" "❌ 屏蔽IP $ip 失败" fi } # 主函数 main() { echo "==============================================" log "INFO" "阿里云安全组IP屏蔽脚本启动" echo "==============================================" # 检查root权限 if [ "$(id -u)" -ne 0 ]; then log "ERROR" "此脚本必须以root用户身份运行" exit 1 fi check_dependencies setup_aliyun_cli analyze_logs check_ip_location # 清理临时文件 rm -f $TMP_IP_FILE $TMP_COUNTRY_FILE log "INFO" "√ 临时文件已清理" echo "==============================================" log "INFO" "脚本执行完成" echo "==============================================" } # 执行主函数 main