first commit

This commit is contained in:
wzj 2025-04-13 10:07:12 +08:00
commit b5269d2826
2 changed files with 292 additions and 0 deletions

130
README.md Normal file
View File

@ -0,0 +1,130 @@
```markdown
# 阿里云安全组动态IP更新工具CentOS 7.9 适用)
![CentOS 7.9](https://img.shields.io/badge/CentOS-7.9-blue)
![阿里云CLI](https://img.shields.io/badge/Aliyun-CLI-orange)
用于动态更新阿里云安全组规则的自动化脚本,特别适配 CentOS 7.9 系统环境。
## 核心功能
- ✅ 自动检测公网IP变动
- ✅ 批量更新多安全组规则
- ✅ 智能迁移旧IP规则到新IP
- ✅ 严格验证协议和端口规则
- ✅ 自动记录IP变更历史
## 系统要求
- CentOS 7.9 操作系统
- 已配置阿里云API访问权限
- 基础工具:`curl``jq`
## 安装指南
### 1. 安装基础依赖
```bash
sudo yum install -y curl jq
```
### 2. 安装阿里云CLI二进制方式
![下载及教程地址](https://help.aliyun.com/zh/cli/install-cli-on-linux?spm=a2c4g.11186623.help-menu-29991.d_2_2.3745606fJSX2wt)
```bash
# 解压安装包
tar -zxvf aliyun-cli-linux-latest-amd64.tgz -C /usr/local/bin/
# 设置执行权限
chmod +x /usr/local/bin/aliyun
# 验证安装
aliyun --version
```
### 3. 配置阿里云CLI
```bash
aliyun configure
```
按照提示输入:
- AccessKey ID
- AccessKey Secret
- 默认地域ID`cn-beijing`
- 输出格式选择 `json`
## 脚本配置
编辑 `alisg.sh` 修改以下参数:
```bash
# 必填配置
REGION="cn-beijing" # 您的阿里云地域
SECURITY_GROUP_IDS=("sg-2zebj4i9uydml05xwejg") # 安全组ID数组
LOG_FILE="/var/log/ip-update.log" # 推荐使用绝对路径
# 可选调试参数
# _LAST_IP="142.171.168.162" # 手动指定旧IP
# _CURRENT_IP="115.171.170.151" # 手动指定新IP
```
## 使用方法
### 首次运行(测试模式)
```bash
chmod +x alisg.sh
./alisg.sh
```
### 生产环境建议
```bash
# 1. 创建专用目录
sudo mkdir -p /opt/aliyun_sg
sudo cp alisg.sh /opt/aliyun_sg/
sudo chown root:root /opt/aliyun_sg/alisg.sh
# 2. 设置定时任务(每小时检查)
echo "0 * * * * root /opt/aliyun_sg/alisg.sh >> /var/log/ip-update.log 2>&1" | sudo tee /etc/cron.d/aliyun_sg_update
```
## 日志监控
建议定期检查日志文件:
```bash
tail -f /var/log/ip-update.log
```
典型成功日志示例:
```
[2023-11-15 14:00:01] 检测到IP变更
旧IP142.171.168.162
新IP115.171.170.151
安全组 sg-2zebj4i9uydml05xwejg 处理完成:
- 已移除 TCP/22/22 规则
- 已添加 TCP/22/22 规则新IP
IP日志已更新
```
## 安全建议
1. 限制日志文件权限:
```bash
sudo chmod 600 /var/log/ip-update.log
```
2. 使用最小权限的AccessKey
3. 定期备份安全组规则:
```bash
aliyun ecs DescribeSecurityGroupAttribute --RegionId $REGION --SecurityGroupId $SG_ID > sg_backup.json
```
## 故障排除
| 错误现象 | 解决方案 |
|---------|----------|
| `aliyun: command not found` | 检查PATH或使用完整路径 `/usr/local/bin/aliyun` |
| 权限拒绝错误 | 使用 `sudo` 或检查AccessKey权限 |
| JSON解析错误 | 安装正确版本的 `jq` 工具 |
## 许可证
MIT License - 自由使用和修改
```

162
alisg.sh Normal file
View File

@ -0,0 +1,162 @@
#!/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