#!/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
版权归属:
musan
许可协议:
本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
评论区