mirror of
https://github.com/yshtcn/alicloud-ip-updater.git
synced 2025-12-14 02:20:18 +08:00
# 20240605-1
- 增加了使用server酱,现在可以通过配置key和自定义的语句在更新或重大错误时发送通知。
This commit is contained in:
parent
a57a15343a
commit
e5400aa800
@ -33,7 +33,7 @@ def load_config(config_file, sample_config_file):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
# 获取IP地址
|
# 获取IP地址
|
||||||
def get_ip_from_service(url):
|
def get_ip_from_service(url, server_chan_key):
|
||||||
try:
|
try:
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
@ -41,10 +41,12 @@ def get_ip_from_service(url):
|
|||||||
return ip
|
return ip
|
||||||
except RequestException as e:
|
except RequestException as e:
|
||||||
logger.error(f"无法从 {url} 获取IP地址: {e}")
|
logger.error(f"无法从 {url} 获取IP地址: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"无法从 {url} 获取IP地址: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# 获取当前安全组的规则
|
# 获取当前安全组的规则
|
||||||
def get_security_group_rules(client, security_group_id):
|
def get_security_group_rules(client, security_group_id, server_chan_key):
|
||||||
try:
|
try:
|
||||||
request = DescribeSecurityGroupAttributeRequest.DescribeSecurityGroupAttributeRequest()
|
request = DescribeSecurityGroupAttributeRequest.DescribeSecurityGroupAttributeRequest()
|
||||||
request.set_SecurityGroupId(security_group_id)
|
request.set_SecurityGroupId(security_group_id)
|
||||||
@ -55,12 +57,14 @@ def get_security_group_rules(client, security_group_id):
|
|||||||
return rules.get('Permissions', {}).get('Permission', [])
|
return rules.get('Permissions', {}).get('Permission', [])
|
||||||
except (ClientException, ServerException) as e:
|
except (ClientException, ServerException) as e:
|
||||||
logger.error(f"无法获取安全组规则: {e}")
|
logger.error(f"无法获取安全组规则: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"无法获取安全组规则: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# 删除带有标记的旧规则
|
# 删除带有标记的旧规则
|
||||||
def delete_old_rules(client, security_group_id, tag):
|
def delete_old_rules(client, security_group_id, tag, server_chan_key):
|
||||||
try:
|
try:
|
||||||
rules = get_security_group_rules(client, security_group_id)
|
rules = get_security_group_rules(client, security_group_id, server_chan_key)
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
if rule.get('Description') == tag:
|
if rule.get('Description') == tag:
|
||||||
request = RevokeSecurityGroupRequest.RevokeSecurityGroupRequest()
|
request = RevokeSecurityGroupRequest.RevokeSecurityGroupRequest()
|
||||||
@ -73,10 +77,12 @@ def delete_old_rules(client, security_group_id, tag):
|
|||||||
client.do_action_with_exception(request)
|
client.do_action_with_exception(request)
|
||||||
except (ClientException, ServerException) as e:
|
except (ClientException, ServerException) as e:
|
||||||
logger.error(f"无法删除旧的安全组规则: {e}")
|
logger.error(f"无法删除旧的安全组规则: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"无法删除旧的安全组规则: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# 更新安全组白名单
|
# 更新安全组白名单
|
||||||
def update_security_group_white_list(client, security_group_id, ip, ports, tag, priority):
|
def update_security_group_white_list(client, security_group_id, ip, ports, tag, priority, server_chan_key, server_chan_title, server_chan_message):
|
||||||
try:
|
try:
|
||||||
for port_info in ports:
|
for port_info in ports:
|
||||||
port = port_info["port"]
|
port = port_info["port"]
|
||||||
@ -97,21 +103,66 @@ def update_security_group_white_list(client, security_group_id, ip, ports, tag,
|
|||||||
|
|
||||||
response = client.do_action_with_exception(request)
|
response = client.do_action_with_exception(request)
|
||||||
logger.info(str(response, encoding='utf-8'))
|
logger.info(str(response, encoding='utf-8'))
|
||||||
|
|
||||||
|
# 发送通知
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_server_chan_notification(server_chan_key, server_chan_title, server_chan_message, ip, ports)
|
||||||
|
|
||||||
except (ClientException, ServerException) as e:
|
except (ClientException, ServerException) as e:
|
||||||
logger.error(f"无法更新安全组白名单: {e}")
|
logger.error(f"无法更新安全组白名单: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"无法更新安全组白名单: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
# 发送Server酱通知
|
||||||
|
def send_server_chan_notification(server_chan_key, title, message, ip, ports):
|
||||||
|
try:
|
||||||
|
title = title.replace("{IP}", ip).replace("{ports}", str(ports))
|
||||||
|
message = message.replace("{IP}", ip).replace("{ports}", str(ports))
|
||||||
|
url = f"https://sctapi.ftqq.com/{server_chan_key}.send"
|
||||||
|
data = {
|
||||||
|
"title": title,
|
||||||
|
"desp": message
|
||||||
|
}
|
||||||
|
response = requests.post(url, data=data)
|
||||||
|
if response.status_code == 200:
|
||||||
|
logger.info("Server酱通知发送成功")
|
||||||
|
else:
|
||||||
|
logger.error(f"Server酱通知发送失败,状态码: {response.status_code}")
|
||||||
|
except RequestException as e:
|
||||||
|
logger.error(f"无法发送Server酱通知: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
# 发送重大错误通知
|
||||||
|
def send_critical_notification(server_chan_key, message):
|
||||||
|
try:
|
||||||
|
url = f"https://sctapi.ftqq.com/{server_chan_key}.send"
|
||||||
|
data = {
|
||||||
|
"title": "重大错误通知",
|
||||||
|
"desp": message
|
||||||
|
}
|
||||||
|
response = requests.post(url, data=data)
|
||||||
|
if response.status_code == 200:
|
||||||
|
logger.info("重大错误通知发送成功")
|
||||||
|
else:
|
||||||
|
logger.error(f"重大错误通知发送失败,状态码: {response.status_code}")
|
||||||
|
except RequestException as e:
|
||||||
|
logger.error(f"无法发送重大错误通知: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# 记录IP地址到本地文件
|
# 记录IP地址到本地文件
|
||||||
def record_ip(ip_record_file, ip_records):
|
def record_ip(ip_record_file, ip_records, server_chan_key):
|
||||||
try:
|
try:
|
||||||
with open(ip_record_file, 'w') as file:
|
with open(ip_record_file, 'w') as file:
|
||||||
json.dump(ip_records, file)
|
json.dump(ip_records, file)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
logger.error(f"无法写入IP记录文件 {ip_record_file}: {e}")
|
logger.error(f"无法写入IP记录文件 {ip_record_file}: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"无法写入IP记录文件 {ip_record_file}: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# 读取本地记录的IP地址
|
# 读取本地记录的IP地址
|
||||||
def load_ip_records(ip_record_file):
|
def load_ip_records(ip_record_file, server_chan_key):
|
||||||
try:
|
try:
|
||||||
if os.path.exists(ip_record_file):
|
if os.path.exists(ip_record_file):
|
||||||
with open(ip_record_file, 'r') as file:
|
with open(ip_record_file, 'r') as file:
|
||||||
@ -121,9 +172,13 @@ def load_ip_records(ip_record_file):
|
|||||||
return {}
|
return {}
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
logger.error(f"无法读取IP记录文件 {ip_record_file}: {e}")
|
logger.error(f"无法读取IP记录文件 {ip_record_file}: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"无法读取IP记录文件 {ip_record_file}: {e}")
|
||||||
raise
|
raise
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
logger.error(f"IP记录文件 {ip_record_file} 解析错误: {e}")
|
logger.error(f"IP记录文件 {ip_record_file} 解析错误: {e}")
|
||||||
|
if server_chan_key and server_chan_key != "your_server_chan_key":
|
||||||
|
send_critical_notification(server_chan_key, f"IP记录文件 {ip_record_file} 解析错误: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -143,6 +198,9 @@ def main():
|
|||||||
PRIORITY = config.get('PRIORITY', 1)
|
PRIORITY = config.get('PRIORITY', 1)
|
||||||
IP_RECORD_FILE = config.get('IP_RECORD_FILE', '/app/config/' + config.get('IP_RECORD_FILE', 'ip_records.json'))
|
IP_RECORD_FILE = config.get('IP_RECORD_FILE', '/app/config/' + config.get('IP_RECORD_FILE', 'ip_records.json'))
|
||||||
INTERVAL_SECONDS = config.get('INTERVAL_SECONDS', 3600)
|
INTERVAL_SECONDS = config.get('INTERVAL_SECONDS', 3600)
|
||||||
|
SERVER_CHAN_KEY = config.get('SERVER_CHAN_KEY', 'your_server_chan_key')
|
||||||
|
SERVER_CHAN_TITLE = config.get('SERVER_CHAN_TITLE', '阿里云安全组白名单更新通知')
|
||||||
|
SERVER_CHAN_MESSAGE = config.get('SERVER_CHAN_MESSAGE', '已新增白名单,IP:{IP},端口: {ports}\n\n注意:在本次更新前,已将系统内有相同tag的规则全部删除。需要手动修改的记录请避免使用同样的tag。')
|
||||||
|
|
||||||
client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION_ID)
|
client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION_ID)
|
||||||
|
|
||||||
@ -150,45 +208,47 @@ def main():
|
|||||||
new_ip_records = {}
|
new_ip_records = {}
|
||||||
|
|
||||||
# 获取并删除旧规则
|
# 获取并删除旧规则
|
||||||
delete_old_rules(client, SECURITY_GROUP_ID, TAG)
|
delete_old_rules(client, SECURITY_GROUP_ID, TAG, SERVER_CHAN_KEY)
|
||||||
|
|
||||||
# 获取新的IP地址并更新安全组白名单
|
# 获取新的IP地址并更新安全组白名单
|
||||||
for url in GETIP_URLS:
|
for url in GETIP_URLS:
|
||||||
ip = get_ip_from_service(url)
|
ip = get_ip_from_service(url, SERVER_CHAN_KEY)
|
||||||
logger.info(f"IP from {url}: {ip}")
|
logger.info(f"IP from {url}: {ip}")
|
||||||
new_ip_records[url] = ip
|
new_ip_records[url] = ip
|
||||||
|
|
||||||
# 更新安全组白名单
|
# 更新安全组白名单
|
||||||
update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY)
|
update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY, SERVER_CHAN_KEY, SERVER_CHAN_TITLE, SERVER_CHAN_MESSAGE)
|
||||||
|
|
||||||
# 记录新的IP地址到本地文件
|
# 记录新的IP地址到本地文件
|
||||||
record_ip(IP_RECORD_FILE, new_ip_records)
|
record_ip(IP_RECORD_FILE, new_ip_records, SERVER_CHAN_KEY)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# 读取本地记录的IP地址
|
# 读取本地记录的IP地址
|
||||||
ip_records = load_ip_records(IP_RECORD_FILE)
|
ip_records = load_ip_records(IP_RECORD_FILE, SERVER_CHAN_KEY)
|
||||||
new_ip_records = {}
|
new_ip_records = {}
|
||||||
|
|
||||||
# 获取新的IP地址并更新安全组白名单
|
# 获取新的IP地址并更新安全组白名单
|
||||||
for url in GETIP_URLS:
|
for url in GETIP_URLS:
|
||||||
ip = get_ip_from_service(url)
|
ip = get_ip_from_service(url, SERVER_CHAN_KEY)
|
||||||
logger.info(f"IP from {url}: {ip}")
|
logger.info(f"IP from {url}: {ip}")
|
||||||
new_ip_records[url] = ip
|
new_ip_records[url] = ip
|
||||||
|
|
||||||
if ip_records.get(url) != ip:
|
if ip_records.get(url) != ip:
|
||||||
# 更新安全组白名单
|
# 更新安全组白名单
|
||||||
update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY)
|
update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY, SERVER_CHAN_KEY, SERVER_CHAN_TITLE, SERVER_CHAN_MESSAGE)
|
||||||
else:
|
else:
|
||||||
logger.info(f"IP from {url} has not changed, no update required.")
|
logger.info(f"IP from {url} has not changed, no update required.IP没有发生变化,本次没有更新")
|
||||||
|
|
||||||
# 记录新的IP地址到本地文件
|
# 记录新的IP地址到本地文件
|
||||||
record_ip(IP_RECORD_FILE, new_ip_records)
|
record_ip(IP_RECORD_FILE, new_ip_records, SERVER_CHAN_KEY)
|
||||||
|
|
||||||
# 等待指定的时间间隔
|
# 等待指定的时间间隔
|
||||||
time.sleep(INTERVAL_SECONDS)
|
time.sleep(INTERVAL_SECONDS)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"程序运行过程中出现错误: {e}")
|
logger.error(f"程序运行过程中出现错误: {e}")
|
||||||
|
if SERVER_CHAN_KEY and SERVER_CHAN_KEY != "your_server_chan_key":
|
||||||
|
send_critical_notification(SERVER_CHAN_KEY, f"程序运行过程中出现错误: {e}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@ -13,6 +13,9 @@
|
|||||||
{"port": "1-65535", "protocol": "tcp"}
|
{"port": "1-65535", "protocol": "tcp"}
|
||||||
],
|
],
|
||||||
"PRIORITY": 1,
|
"PRIORITY": 1,
|
||||||
"IP_RECORD_FILE": "ip_records.json",
|
"IP_RECORD_FILE": "./config/ip_records.json",
|
||||||
"INTERVAL_SECONDS": 3600
|
"INTERVAL_SECONDS": 3600,
|
||||||
|
"SERVER_CHAN_KEY": "your_server_chan_key",
|
||||||
|
"SERVER_CHAN_TITLE": "阿里云安全组白名单更新通知",
|
||||||
|
"SERVER_CHAN_MESSAGE": "已新增白名单,IP:{IP},端口: {ports}\n\n注意:在本次更新前,已将系统内有相同tag的规则全部删除。需要手动修改的记录请避免使用同样的tag。"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user