163 lines
5.6 KiB
Bash
163 lines
5.6 KiB
Bash
#!/bin/bash
|
||
|
||
# 定义一些常量
|
||
REGION="cn-beijing" # 设置区域
|
||
SECURITY_GROUP_IDS=("sg-2zebj4i9uydml05xwejg") # 设置你的安全组ID列表使用空格分隔,例如("sg-2zebj4i9uydml05xwejg" "sg-3jd9dkjs99ddjfksssdqe")
|
||
LOG_FILE="ip-beijing.log" # 存储当前外网IP的日志文件
|
||
|
||
# 允许用户在脚本上方指定 last_ip 和 current_ip,如果为空则使用脚本自动获取(last_ip从LOG_FILE获取,current_ip从公网出口获取)
|
||
_LAST_IP=""
|
||
_CURRENT_IP=""
|
||
|
||
# 获取当前外网IP
|
||
get_current_ip() {
|
||
if [[ -z "$_CURRENT_IP" ]]; then
|
||
_CURRENT_IP=$(curl -s ipinfo.io | grep -oP "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}")
|
||
fi
|
||
echo "$_CURRENT_IP"
|
||
}
|
||
|
||
# 获取上次保存的外网IP
|
||
get_last_ip() {
|
||
if [[ -z "$_LAST_IP" ]]; then
|
||
if [[ -f "$LOG_FILE" ]]; then
|
||
_LAST_IP=$(cat "$LOG_FILE")
|
||
else
|
||
echo "没有找到历史IP,无法比较, 请把需要修改的历史IP加入变量“_LAST_IP”或者写入${LOG_FILE}" >&2
|
||
return 1
|
||
fi
|
||
fi
|
||
echo "$_LAST_IP"
|
||
}
|
||
|
||
# 更新日志文件,保存当前外网IP
|
||
update_ip_log() {
|
||
echo "$1" > "$LOG_FILE"
|
||
}
|
||
|
||
# 获取当前安全组的所有IP规则
|
||
get_security_group_rules() {
|
||
aliyun ecs DescribeSecurityGroupAttribute \
|
||
--RegionId "$REGION" \
|
||
--SecurityGroupId "$1" \
|
||
--NicType "internet" \
|
||
--Direction "ingress" | jq -r '.Permissions.Permission[] | {IpProtocol, SourceCidrIp, PortRange, Description}'
|
||
}
|
||
|
||
# 验证IpProtocol值是否合法
|
||
is_valid_ip_protocol() {
|
||
local protocol=$1
|
||
case "$protocol" in
|
||
"TCP" | "UDP" | "ICMP" | "GRE" | "All") return 0 ;;
|
||
*) return 1 ;;
|
||
esac
|
||
}
|
||
|
||
# 验证PortRange格式是否合法
|
||
is_valid_port_range() {
|
||
local port_range=$1
|
||
if [[ "$port_range" =~ ^[0-9]+/[0-9]+$ ]]; then
|
||
local start_port=$(echo "$port_range" | cut -d'/' -f1)
|
||
local end_port=$(echo "$port_range" | cut -d'/' -f2)
|
||
if [[ "$start_port" -le 65535 && "$end_port" -le 65535 ]]; then
|
||
return 0
|
||
fi
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
# 移除指定的IP规则
|
||
remove_ip_rule() {
|
||
aliyun ecs RevokeSecurityGroup \
|
||
--RegionId "$REGION" \
|
||
--SecurityGroupId "$1" \
|
||
--SourceCidrIp "$2" \
|
||
--IpProtocol "$3" \
|
||
--NicType "internet" \
|
||
--PortRange "$4"
|
||
}
|
||
|
||
# 添加新的IP规则
|
||
add_ip_rule() {
|
||
aliyun ecs AuthorizeSecurityGroup \
|
||
--RegionId "$REGION" \
|
||
--SecurityGroupId "$1" \
|
||
--SourceCidrIp "$2" \
|
||
--IpProtocol "$3" \
|
||
--NicType "internet" \
|
||
--PortRange "$4" \
|
||
--Description "$5"
|
||
}
|
||
|
||
# 主程序
|
||
|
||
# 如果用户没有指定 last_ip 或 current_ip,自动获取
|
||
if [[ -z "$last_ip" ]]; then
|
||
last_ip=$(get_last_ip)
|
||
fi
|
||
if [[ -z "$current_ip" ]]; then
|
||
current_ip=$(get_current_ip)
|
||
fi
|
||
|
||
# 如果IP发生变化
|
||
if [[ "$current_ip" != "$last_ip" ]]; then
|
||
echo "修改后IP:$current_ip"
|
||
echo "修改前IP:$last_ip"
|
||
[ -z $last_ip ] && exit
|
||
# 遍历所有安全组ID并更新规则
|
||
for sg_id in "${SECURITY_GROUP_IDS[@]}"; do
|
||
# 获取当前安全组的规则
|
||
rules=$(get_security_group_rules "$sg_id")
|
||
|
||
# 查找并移除旧的IP规则
|
||
if [[ -z "$rules" ]]; then
|
||
echo "没有找到任何安全组规则,无需处理"
|
||
exit 0
|
||
fi
|
||
|
||
found_rules=false
|
||
for rule in $(echo "$rules" | jq -r '.SourceCidrIp + "," + .IpProtocol + "," + .PortRange + "," + .Description' | grep $last_ip); do
|
||
# 获取规则中的SourceCidrIp, IpProtocol 和 PortRange
|
||
source_ip=$(echo "$rule" | awk -F',' '{print $1}')
|
||
ip_protocol=$(echo "$rule" | awk -F',' '{print $2}')
|
||
port_range=$(echo "$rule" | awk -F',' '{print $3}')
|
||
description=$(echo "$rule" | awk -F',' '{print $4}')
|
||
# 如果该规则的 IP 是旧 IP,则移除它
|
||
if [[ "$source_ip" == "$last_ip/32" || "$source_ip" == "$last_ip" ]]; then
|
||
# 验证IpProtocol和PortRange的合法性
|
||
if is_valid_ip_protocol "$ip_protocol" && is_valid_port_range "$port_range"; then
|
||
echo "移除旧规则:$source_ip $ip_protocol $port_range $description"
|
||
remove_ip_rule "$sg_id" "$source_ip" "$ip_protocol" "$port_range" | jq '.RequestId'
|
||
else
|
||
echo "无效的规则:$source_ip $ip_protocol $port_range"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
if [[ "$found_rules" == false ]]; then
|
||
echo "没有找到匹配 $last_ip 的旧规则,无需操作"
|
||
exit 0
|
||
fi
|
||
|
||
# 添加新的IP规则
|
||
for rule in $(echo "$rules" | jq -r '.SourceCidrIp + "," + .IpProtocol + "," + .PortRange + "," + .Description' | grep $last_ip); do
|
||
ip_protocol=$(echo "$rule" | awk -F',' '{print $2}')
|
||
port_range=$(echo "$rule" | awk -F',' '{print $3}')
|
||
description=$(echo "$rule" | awk -F',' '{print $4}')
|
||
# 验证IpProtocol和PortRange的合法性
|
||
if is_valid_ip_protocol "$ip_protocol" && is_valid_port_range "$port_range"; then
|
||
echo "添加新的规则:$current_ip $current_ip/32 $ip_protocol $port_range $description"
|
||
add_ip_rule "$sg_id" "$current_ip/32" "$ip_protocol" "$port_range" "$description" | jq '.RequestId'
|
||
else
|
||
echo "无效的规则:$current_ip $ip_protocol $port_range"
|
||
fi
|
||
done
|
||
done
|
||
|
||
# 更新日志文件,保存当前IP
|
||
update_ip_log "$current_ip"
|
||
else
|
||
echo "IP没有变化,脚本不会进行任何操作"
|
||
fi
|
||
|