mirror of
https://github.com/jaaazzz/GetCFipToDns.git
synced 2026-05-06 15:20:51 +08:00
first commit
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
.DS_Store
|
||||
__pycache__
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
cf2dns.log
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
config.json
|
||||
45
README.md
Normal file
45
README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
### 功能介绍
|
||||
|
||||
本项目的主要功能是动态获取cf优选ip,并将域名实时解析到这些优选IP上,以达到网站使用cloudflare CDN并使用国内访问速度更快的CDN节点。
|
||||
★ 动态获取cf优选ip的接口由vps789.com提供
|
||||
★ 网站使用CF优选IP的教程参考:https://www.vpsjxw.com/vps_use/cloudflare_select_ip/
|
||||
★ 本工具主要是将网站域名动态解析到获取到的优选ip上,目前支持阿里云DNS、DNSPod、华为云DNS、NameSilo
|
||||
|
||||
### VPS789.com提供CF优选IP接口
|
||||
1、支持对CF优选IP的三网实时监测延迟、丢包率,支持查看24小时、一个月的监测数据。
|
||||
|
||||
2、支持对CF优选IP的下载速度进行测试
|
||||
|
||||
3、基于CloudFlareST工具生成一个优选IP池,vps789的优选IP每天定时淘汰1/3网络不好的IP,从优选IP池补充到vps789中继续监测。通过持续补充优选IP和IP优胜略汰机制,保证vps789上的IP都是优中选优。
|
||||
|
||||
4、vps789优选IP监控页面地址:https://vps789.com/cfip
|
||||
|
||||
### 使用方法
|
||||
|
||||
0. 需要python3、pip环境
|
||||
|
||||
1. 安装运行脚本所需依赖
|
||||
|
||||
```python
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
1. 登录DNS解析平台,获取 SecretId、SecretKey。
|
||||
如果使用阿里云DNS,注意需要添加DNS控制权限**AliyunDNSFullAccess**
|
||||
如果使用NameSilo只用填SecretKey即可。
|
||||
|
||||
2. 将脚本下载到本地修改start.py中的SecretId、SecretKey
|
||||
|
||||
3. 修改脚本中域名配置信息,可配置多个域名和多个子域名,注意选择DNS服务商
|
||||
|
||||
|
||||
4. 运行程序,如果能够正常运行可以选择cron定时执行(建议1个小时执行一次)
|
||||
|
||||
```python
|
||||
python start.py
|
||||
```
|
||||
|
||||
### 鸣谢
|
||||
感谢以下项目提供技术支撑与实现思路
|
||||
[cf2dns](https://github.com/ddgth/cf2dns)@ddgth
|
||||
[CloudflareSpeedTest](https://github.com/XIU2/CloudflareSpeedTest)@XIU2
|
||||
0
dns/__init__.py
Normal file
0
dns/__init__.py
Normal file
89
dns/aliyun.py
Normal file
89
dns/aliyun.py
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Mail: tongdongdong@outlook.com
|
||||
# Reference: https://help.aliyun.com/document_detail/29776.html?spm=a2c4g.11186623.2.38.3fc33efexrOFkT
|
||||
# REGION: https://help.aliyun.com/document_detail/198326.html
|
||||
import json
|
||||
from aliyunsdkcore import client
|
||||
from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest
|
||||
from aliyunsdkalidns.request.v20150109 import DeleteDomainRecordRequest
|
||||
from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest
|
||||
from aliyunsdkalidns.request.v20150109 import AddDomainRecordRequest
|
||||
|
||||
|
||||
rc_format = 'json'
|
||||
class AliApi():
|
||||
def __init__(self, ACCESSID, SECRETKEY, REGION='cn-hongkong'):
|
||||
self.access_key_id = ACCESSID
|
||||
self.access_key_secret = SECRETKEY
|
||||
self.region = REGION
|
||||
|
||||
def del_record(self, domain, record):
|
||||
clt = client.AcsClient(self.access_key_id, self.access_key_secret, self.region)
|
||||
request = DeleteDomainRecordRequest.DeleteDomainRecordRequest()
|
||||
request.set_RecordId(record)
|
||||
request.set_accept_format(rc_format)
|
||||
result = clt.do_action(request).decode('utf-8')
|
||||
result = json.JSONDecoder().decode(result)
|
||||
return result
|
||||
|
||||
def get_record(self, domain, length, sub_domain, record_type):
|
||||
clt = client.AcsClient(self.access_key_id, self.access_key_secret, self.region)
|
||||
request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
|
||||
request.set_DomainName(domain)
|
||||
request.set_PageSize(length)
|
||||
request.set_RRKeyWord(sub_domain)
|
||||
request.set_Type(record_type)
|
||||
request.set_accept_format(rc_format)
|
||||
result = clt.do_action(request).decode('utf-8').replace('DomainRecords', 'data', 1).replace('Record', 'records', 1).replace('RecordId', 'id').replace('Value', 'value').replace('Line', 'line').replace('telecom', '电信').replace('unicom', '联通').replace('mobile', '移动').replace('oversea', '境外').replace('default', '默认')
|
||||
result = json.JSONDecoder().decode(result)
|
||||
return result
|
||||
|
||||
def create_record(self, domain, sub_domain, value, record_type, line, ttl):
|
||||
clt = client.AcsClient(self.access_key_id, self.access_key_secret, self.region)
|
||||
request = AddDomainRecordRequest.AddDomainRecordRequest()
|
||||
request.set_DomainName(domain)
|
||||
request.set_RR(sub_domain)
|
||||
if line == "电信":
|
||||
line = "telecom"
|
||||
elif line == "联通":
|
||||
line = "unicom"
|
||||
elif line == "移动":
|
||||
line = "mobile"
|
||||
elif line == "境外":
|
||||
line = "oversea"
|
||||
elif line == "默认":
|
||||
line = "default"
|
||||
request.set_Line(line)
|
||||
request.set_Type(record_type)
|
||||
request.set_Value(value)
|
||||
request.set_TTL(ttl)
|
||||
request.set_accept_format(rc_format)
|
||||
result = clt.do_action(request).decode('utf-8')
|
||||
result = json.JSONDecoder().decode(result)
|
||||
return result
|
||||
|
||||
def change_record(self, domain, record_id, sub_domain, value, record_type, line, ttl):
|
||||
clt = client.AcsClient(self.access_key_id, self.access_key_secret, self.region)
|
||||
request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
|
||||
request.set_RR(sub_domain)
|
||||
request.set_RecordId(record_id)
|
||||
if line == "电信":
|
||||
line = "telecom"
|
||||
elif line == "联通":
|
||||
line = "unicom"
|
||||
elif line == "移动":
|
||||
line = "mobile"
|
||||
elif line == "境外":
|
||||
line = "oversea"
|
||||
elif line == "默认":
|
||||
line = "default"
|
||||
request.set_Line(line)
|
||||
request.set_Type(record_type)
|
||||
request.set_Value(value)
|
||||
request.set_TTL(ttl)
|
||||
request.set_accept_format(rc_format)
|
||||
result = clt.do_action(request).decode('utf-8')
|
||||
result = json.JSONDecoder().decode(result)
|
||||
return result
|
||||
|
||||
115
dns/huawei.py
Normal file
115
dns/huawei.py
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Author/Mail: tongdongdong@outlook.com
|
||||
# Reference1: https://github.com/huaweicloud/huaweicloud-sdk-python-v3/tree/ff7df92d2a496871c7c2d84dfd2a7f4e2467fff5/huaweicloud-sdk-dns/huaweicloudsdkdns/v2/model
|
||||
# Reference2: https://support.huaweicloud.com/api-dns/dns_api_65003.html
|
||||
# REGION: https://developer.huaweicloud.com/endpoint
|
||||
|
||||
from re import sub
|
||||
from huaweicloudsdkcore.auth.credentials import BasicCredentials
|
||||
from huaweicloudsdkdns.v2 import *
|
||||
from huaweicloudsdkdns.v2.region.dns_region import DnsRegion
|
||||
import json
|
||||
|
||||
|
||||
class HuaWeiApi():
|
||||
def __init__(self, ACCESSID, SECRETKEY, REGION = 'cn-east-3'):
|
||||
self.AK = ACCESSID
|
||||
self.SK = SECRETKEY
|
||||
self.region = REGION
|
||||
self.client = DnsClient.new_builder().with_credentials(BasicCredentials(self.AK, self.SK)).with_region(DnsRegion.value_of(self.region)).build()
|
||||
self.zone_id = self.get_zones()
|
||||
|
||||
def del_record(self, domain, record):
|
||||
request = DeleteRecordSetsRequest()
|
||||
request.zone_id = self.zone_id[domain + '.']
|
||||
request.recordset_id = record
|
||||
response = self.client.delete_record_sets(request)
|
||||
result = json.loads(str(response))
|
||||
print(result)
|
||||
return result
|
||||
|
||||
def get_record(self, domain, length, sub_domain, record_type):
|
||||
request = ListRecordSetsWithLineRequest()
|
||||
request.limit = length
|
||||
request.type = record_type
|
||||
if sub_domain == '@':
|
||||
request.name = domain + "."
|
||||
else:
|
||||
request.name = sub_domain + '.' + domain + "."
|
||||
response = self.client.list_record_sets_with_line(request)
|
||||
data = json.loads(str(response))
|
||||
result = {}
|
||||
records_temp = []
|
||||
for record in data['recordsets']:
|
||||
if (sub_domain == '@' and domain + "." == record['name']) or (sub_domain + '.' + domain + "." == record['name']):
|
||||
record['line'] = self.line_format(record['line'])
|
||||
record['value'] = '1.1.1.1'
|
||||
records_temp.append(record)
|
||||
result['data'] = {'records': records_temp}
|
||||
return result
|
||||
|
||||
def create_record(self, domain, sub_domain, value, record_type, line, ttl):
|
||||
request = CreateRecordSetWithLineRequest()
|
||||
request.zone_id = self.zone_id[domain + '.']
|
||||
if sub_domain == '@':
|
||||
name = domain + "."
|
||||
else:
|
||||
name = sub_domain + '.' + domain + "."
|
||||
request.body = CreateRecordSetWithLineReq(
|
||||
type = record_type,
|
||||
name = name,
|
||||
ttl = ttl,
|
||||
weight = 1,
|
||||
records = [value],
|
||||
line = self.line_format(line)
|
||||
)
|
||||
response = self.client.create_record_set_with_line(request)
|
||||
result = json.loads(str(response))
|
||||
return result
|
||||
|
||||
def change_record(self, domain, record_id, sub_domain, value, record_type, line, ttl):
|
||||
request = UpdateRecordSetRequest()
|
||||
request.zone_id = self.zone_id[domain + '.']
|
||||
request.recordset_id = record_id
|
||||
if sub_domain == '@':
|
||||
name = domain + "."
|
||||
else:
|
||||
name = sub_domain + '.' + domain + "."
|
||||
request.body = UpdateRecordSetReq(
|
||||
name = name,
|
||||
type = record_type,
|
||||
ttl = ttl,
|
||||
records=[value]
|
||||
)
|
||||
response = self.client.update_record_set(request)
|
||||
result = json.loads(str(response))
|
||||
return result
|
||||
|
||||
def get_zones(self):
|
||||
request = ListPublicZonesRequest()
|
||||
response = self.client.list_public_zones(request)
|
||||
result = json.loads(str(response))
|
||||
zone_id = {}
|
||||
for zone in result['zones']:
|
||||
zone_id[zone['name']] = zone['id']
|
||||
return zone_id
|
||||
|
||||
def line_format(self, line):
|
||||
lines = {
|
||||
'默认' : 'default_view',
|
||||
'电信' : 'Dianxin',
|
||||
'联通' : 'Liantong',
|
||||
'移动' : 'Yidong',
|
||||
'境外' : 'Abroad',
|
||||
'default_view' : '默认',
|
||||
'Dianxin' : '电信',
|
||||
'Liantong' : '联通',
|
||||
'Yidong' : '移动',
|
||||
'Abroad' : '境外',
|
||||
}
|
||||
return lines.get(line, None)
|
||||
|
||||
if __name__ == '__main__':
|
||||
hw_api = HuaWeiApi('WTTCWxxxxxxxxx84O0V', 'GXkG6D4X1Nxxxxxxxxxxxxxxxxxxxxx4lRg6lT')
|
||||
print(hw_api.get_record('xxxx.com', 100, '@', 'A'))
|
||||
60
dns/nameSilo.py
Normal file
60
dns/nameSilo.py
Normal file
@@ -0,0 +1,60 @@
|
||||
import logging
|
||||
import copy
|
||||
import sys
|
||||
import json
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class NameSiloClient:
|
||||
|
||||
|
||||
def __init__(self, key) -> None:
|
||||
self._api_key = key
|
||||
|
||||
|
||||
def get_record(self, domain):
|
||||
|
||||
try:
|
||||
url = f"https://www.namesilo.com/api/dnsListRecords?version=1&type=json&key={self._api_key}&domain={domain}"
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
def delete_record(self, domain,recordId):
|
||||
|
||||
try:
|
||||
url = f"https://www.namesilo.com/api/dnsDeleteRecord?version=1&type=json&key={self._api_key}&domain={domain}&rrid={recordId}"
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
def create_record(self, domain, sub_domain, value, record_type, ttl):
|
||||
try:
|
||||
url = f"https://www.namesilo.com/api/dnsAddRecord?version=1&type=json&key={self._api_key}&domain={domain}&rrtype={record_type}&rrhost={sub_domain}&rrvalue={value}&rrttl={ttl}"
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
def change_record(self, domain, record_id, sub_domain, value, ttl):
|
||||
try:
|
||||
url = f"https://www.namesilo.com/api/dnsUpdateRecord?version=1&type=json&key={self._api_key}&domain={domain}&rrid={record_id}&rrhost={sub_domain}&rrvalue={value}&rrttl={ttl}"
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
return None
|
||||
129
dns/qCloud.py
Normal file
129
dns/qCloud.py
Normal file
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Mail: tongdongdong@outlook.com
|
||||
# Reference: https://cloud.tencent.com/document/product/302/8517
|
||||
# QcloudApiv3 DNSPod 的 API 更新了 By github@z0z0r4
|
||||
|
||||
import json
|
||||
from tencentcloud.common import credential
|
||||
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
|
||||
from tencentcloud.dnspod.v20210323 import dnspod_client, models
|
||||
|
||||
class QcloudApiv3():
|
||||
def __init__(self, SECRETID, SECRETKEY):
|
||||
self.SecretId = SECRETID
|
||||
self.secretKey = SECRETKEY
|
||||
self.cred = credential.Credential(SECRETID, SECRETKEY)
|
||||
|
||||
def del_record(self, domain: str, record_id: int):
|
||||
client = dnspod_client.DnspodClient(self.cred, "")
|
||||
req_model = models.DeleteRecordRequest()
|
||||
params = {
|
||||
"Domain": domain,
|
||||
"RecordId": record_id
|
||||
}
|
||||
req_model.from_json_string(json.dumps(params))
|
||||
|
||||
|
||||
resp = client.DeleteRecord(req_model)
|
||||
resp = json.loads(resp.to_json_string())
|
||||
resp["code"] = 0
|
||||
resp["message"] = "None"
|
||||
return resp
|
||||
|
||||
def get_record(self, domain: str, length: int, sub_domain: str, record_type: str):
|
||||
def format_record(record: dict):
|
||||
new_record = {}
|
||||
record["id"] = record['RecordId']
|
||||
for key in record:
|
||||
new_record[key.lower()] = record[key]
|
||||
return new_record
|
||||
try:
|
||||
client = dnspod_client.DnspodClient(self.cred, "")
|
||||
|
||||
req_model = models.DescribeRecordListRequest()
|
||||
params = {
|
||||
"Domain": domain,
|
||||
"Subdomain": sub_domain,
|
||||
"RecordType": record_type,
|
||||
"Limit": length
|
||||
}
|
||||
req_model.from_json_string(json.dumps(params))
|
||||
|
||||
|
||||
resp = client.DescribeRecordList(req_model)
|
||||
resp = json.loads(resp.to_json_string())
|
||||
temp_resp = {}
|
||||
temp_resp["code"] = 0
|
||||
temp_resp["data"] = {}
|
||||
temp_resp["data"]["records"] = []
|
||||
for record in resp['RecordList']:
|
||||
temp_resp["data"]["records"].append(format_record(record))
|
||||
temp_resp["data"]["domain"] = {}
|
||||
temp_resp["data"]["domain"]["grade"] = self.get_domain(domain)["DomainInfo"]["Grade"] # DP_Free
|
||||
return temp_resp
|
||||
except TencentCloudSDKException:
|
||||
# 构造空响应...
|
||||
temp_resp = {}
|
||||
temp_resp["code"] = 0
|
||||
temp_resp["data"] = {}
|
||||
temp_resp["data"]["records"] = []
|
||||
temp_resp["data"]["domain"] = {}
|
||||
temp_resp["data"]["domain"]["grade"] = self.get_domain(domain)["DomainInfo"]["Grade"] # DP_Free
|
||||
return temp_resp
|
||||
|
||||
def create_record(self, domain: str, sub_domain: str, value: int, record_type: str = "A", line: str = "默认", ttl: int = 600):
|
||||
client = dnspod_client.DnspodClient(self.cred, "")
|
||||
req = models.CreateRecordRequest()
|
||||
params = {
|
||||
"Domain": domain,
|
||||
"SubDomain": sub_domain,
|
||||
"RecordType": record_type,
|
||||
"RecordLine": line,
|
||||
"Value": value,
|
||||
"ttl": ttl
|
||||
}
|
||||
req.from_json_string(json.dumps(params))
|
||||
|
||||
# 返回的resp是一个CreateRecordResponse的实例,与请求对象对应
|
||||
resp = client.CreateRecord(req)
|
||||
resp = json.loads(resp.to_json_string())
|
||||
resp["code"] = 0
|
||||
resp["message"] = "None"
|
||||
return resp
|
||||
|
||||
def change_record(self, domain: str, record_id: int, sub_domain: str, value: str, record_type: str = "A", line: str = "默认", ttl: int = 600):
|
||||
client = dnspod_client.DnspodClient(self.cred, "")
|
||||
req = models.ModifyRecordRequest()
|
||||
params = {
|
||||
"Domain": domain,
|
||||
"SubDomain": sub_domain,
|
||||
"RecordType": record_type,
|
||||
"RecordLine": line,
|
||||
"Value": value,
|
||||
"TTL": ttl,
|
||||
"RecordId": record_id
|
||||
}
|
||||
req.from_json_string(json.dumps(params))
|
||||
|
||||
# 返回的resp是一个ChangeRecordResponse的实例,与请求对象对应
|
||||
resp = client.ModifyRecord(req)
|
||||
resp = json.loads(resp.to_json_string())
|
||||
resp["code"] = 0
|
||||
resp["message"] = "None"
|
||||
return resp
|
||||
|
||||
def get_domain(self, domain: str):
|
||||
client = dnspod_client.DnspodClient(self.cred, "")
|
||||
|
||||
# 实例化一个请求对象,每个接口都会对应一个request对象
|
||||
req = models.DescribeDomainRequest()
|
||||
params = {
|
||||
"Domain": domain
|
||||
}
|
||||
req.from_json_string(json.dumps(params))
|
||||
|
||||
# 返回的resp是一个DescribeDomainResponse的实例,与请求对象对应
|
||||
resp = client.DescribeDomain(req)
|
||||
resp = json.loads(resp.to_json_string())
|
||||
return resp
|
||||
38
log.py
Normal file
38
log.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import logging
|
||||
from logging import handlers
|
||||
|
||||
class Logger(object):
|
||||
level_relations = {
|
||||
'debug':logging.DEBUG,
|
||||
'info':logging.INFO,
|
||||
'warning':logging.WARNING,
|
||||
'error':logging.ERROR,
|
||||
'crit':logging.CRITICAL
|
||||
}#日志级别关系映射
|
||||
|
||||
def __init__(self,filename,level='info',when='D',backCount=3,fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
|
||||
self.logger = logging.getLogger(filename)
|
||||
format_str = logging.Formatter(fmt)#设置日志格式
|
||||
self.logger.setLevel(self.level_relations.get(level))#设置日志级别
|
||||
sh = logging.StreamHandler()#往屏幕上输出
|
||||
sh.setFormatter(format_str) #设置屏幕上显示的格式
|
||||
th = handlers.TimedRotatingFileHandler(filename=filename,when=when,backupCount=backCount,encoding='utf-8')#往文件里写入#指定间隔时间自动生成文件的处理器
|
||||
#实例化TimedRotatingFileHandler
|
||||
#interval是时间间隔,backupCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种:
|
||||
# S 秒
|
||||
# M 分
|
||||
# H 小时、
|
||||
# D 天、
|
||||
# W 每星期(interval==0时代表星期一)
|
||||
# midnight 每天凌晨
|
||||
th.setFormatter(format_str)#设置文件里写入的格式
|
||||
self.logger.addHandler(sh) #把对象加到logger里
|
||||
self.logger.addHandler(th)
|
||||
if __name__ == '__main__':
|
||||
log = Logger('monitor.log',level='debug')
|
||||
log.logger.debug('debug')
|
||||
log.logger.info('info')
|
||||
log.logger.warning('警告')
|
||||
log.logger.error('报错')
|
||||
log.logger.critical('严重')
|
||||
Logger('error.log', level='error').logger.error('error')
|
||||
6
requirements.txt
Normal file
6
requirements.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
aliyun-python-sdk-alidns==2.6.19
|
||||
aliyun-python-sdk-core==2.13.29
|
||||
huaweicloudsdkcore==3.1.5
|
||||
huaweicloudsdkdns==3.1.5
|
||||
requests==2.28.1
|
||||
tencentcloud-sdk-python==3.0.806
|
||||
205
start.py
Normal file
205
start.py
Normal file
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import random
|
||||
import time
|
||||
import requests
|
||||
from dns.qCloud import QcloudApiv3 # QcloudApiv3 DNSPod 的 API 更新了 By github@z0z0r4
|
||||
from dns.aliyun import AliApi
|
||||
from dns.huawei import HuaWeiApi
|
||||
from dns.nameSilo import NameSiloClient
|
||||
from log import Logger
|
||||
import traceback
|
||||
|
||||
|
||||
#CM:移动 CU:联通 CT:电信 AB:境外 DEF:默认
|
||||
#修改需要更改的dnspod域名和子域名
|
||||
DOMAINS = {
|
||||
"quanxxxhost.com": {"@": ["CM","CU","CT"]}
|
||||
}
|
||||
|
||||
#解析生效条数
|
||||
#免费的DNSPod相同线路最多支持2条解析
|
||||
AFFECT_NUM = 2
|
||||
|
||||
#DNS解析服务商 DNSPod-1 阿里云-2 如华为云-3 NameSilo-4
|
||||
DNS_SERVER = 4
|
||||
|
||||
#如果使用华为云解析 需要从API凭证-项目列表中获取
|
||||
REGION_HW = 'cn-east-3'
|
||||
|
||||
#如果使用阿里云解析 REGION出现错误再修改 默认不需要修改 https://help.aliyun.com/document_detail/198326.html
|
||||
REGION_ALI = 'cn-hongkong'
|
||||
|
||||
#解析生效时间,默认为600秒 如果不是DNS付费版用户 不要修改!!!
|
||||
#如果是NameSilo解析最小为3600
|
||||
TTL = 600
|
||||
|
||||
#v4为筛选出IPv4的IP v6为筛选出IPv6的IP
|
||||
#目前仅支持v4
|
||||
TYPE = 'v4'
|
||||
|
||||
#API 密钥
|
||||
#腾讯云后台获取 https://console.cloud.tencent.com/cam/capi
|
||||
#阿里云后台获取 https://help.aliyun.com/document_detail/53045.html?spm=a2c4g.11186623.2.11.2c6a2fbdh13O53 注意需要添加DNS控制权限 AliyunDNSFullAccess
|
||||
#华为云后台获取 https://support.huaweicloud.com/devg-apisign/api-sign-provide-aksk.html
|
||||
#NameSilo后台获取 https://www.namesilo.com/account/api-manager NameSilo只用填SECRETKEY即可
|
||||
SECRETID = 'LTAI5xxxxxxxxxYWRedp9Y'
|
||||
SECRETKEY = '7288bxxxxxxxxx23a332'
|
||||
|
||||
log_cf2dns = Logger('cf2dns.log', level='debug')
|
||||
|
||||
def get_optimization_ip():
|
||||
try:
|
||||
headers = headers = {'Content-Type': 'application/json'}
|
||||
data = {}
|
||||
response = requests.post('https://vps789.com/public/sum/cfIpApi', json=data, headers=headers)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
log_cf2dns.logger.error("CHANGE OPTIMIZATION IP ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----MESSAGE: REQUEST STATUS CODE IS NOT 200")
|
||||
return None
|
||||
except Exception as e:
|
||||
log_cf2dns.logger.error("CHANGE OPTIMIZATION IP ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----MESSAGE: " + str(e))
|
||||
return None
|
||||
|
||||
#s_info已存在的ip,c_info 最新的优选cfip
|
||||
def changeDNS(line, s_info, c_info, domain, sub_domain, cloud):
|
||||
global AFFECT_NUM, TYPE
|
||||
if TYPE == 'v6':
|
||||
recordType = "AAAA"
|
||||
else:
|
||||
recordType = "A"
|
||||
|
||||
lines = {"CM": "移动", "CU": "联通", "CT": "电信", "AB": "境外", "DEF": "默认"}
|
||||
line = lines[line]
|
||||
|
||||
try:
|
||||
create_num = AFFECT_NUM - len(s_info)
|
||||
# 如果线路能解析的ip已满,就用cfip一个一个去替换原来的ip解析
|
||||
if create_num == 0:
|
||||
for info in s_info:
|
||||
if len(c_info) == 0:
|
||||
break
|
||||
cf_ip = c_info.pop(random.randint(0,len(c_info)-1))["ip"]
|
||||
if cf_ip in str(s_info):
|
||||
continue
|
||||
ret = cloud.change_record(domain, info["recordId"], sub_domain, cf_ip, recordType, line, TTL)
|
||||
if(DNS_SERVER != 1 or ret["code"] == 0):
|
||||
log_cf2dns.logger.info("CHANGE DNS SUCCESS: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+line+"----RECORDID: " + str(info["recordId"]) + "----VALUE: " + cf_ip )
|
||||
else:
|
||||
log_cf2dns.logger.error("CHANGE DNS ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+line+"----RECORDID: " + str(info["recordId"]) + "----VALUE: " + cf_ip + "----MESSAGE: " + ret["message"] )
|
||||
# 如果线路还可以解析更多的ip,就添加cfip解析,直到用完
|
||||
elif create_num > 0:
|
||||
for i in range(create_num):
|
||||
if len(c_info) == 0:
|
||||
break
|
||||
cf_ip = c_info.pop(random.randint(0,len(c_info)-1))["ip"]
|
||||
if cf_ip in str(s_info):
|
||||
continue
|
||||
ret = cloud.create_record(domain, sub_domain, cf_ip, recordType, line, TTL)
|
||||
if(DNS_SERVER != 1 or ret["code"] == 0):
|
||||
log_cf2dns.logger.info("CREATE DNS SUCCESS: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+line+"----VALUE: " + cf_ip )
|
||||
else:
|
||||
log_cf2dns.logger.error("CREATE DNS ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+line+"----RECORDID: " + str(info["recordId"]) + "----VALUE: " + cf_ip + "----MESSAGE: " + ret["message"] )
|
||||
# 如果线路能解析的ip已超出配额,就用cfip一个一个去替换原来的ip解析
|
||||
else:
|
||||
for info in s_info:
|
||||
if create_num == 0 or len(c_info) == 0:
|
||||
break
|
||||
cf_ip = c_info.pop(random.randint(0,len(c_info)-1))["ip"]
|
||||
if cf_ip in str(s_info):
|
||||
create_num += 1
|
||||
continue
|
||||
ret = cloud.change_record(domain, info["recordId"], sub_domain, cf_ip, recordType, line, TTL)
|
||||
if(DNS_SERVER != 1 or ret["code"] == 0):
|
||||
log_cf2dns.logger.info("CHANGE DNS SUCCESS: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+line+"----RECORDID: " + str(info["recordId"]) + "----VALUE: " + cf_ip )
|
||||
else:
|
||||
log_cf2dns.logger.error("CHANGE DNS ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+line+"----RECORDID: " + str(info["recordId"]) + "----VALUE: " + cf_ip + "----MESSAGE: " + ret["message"] )
|
||||
create_num += 1
|
||||
except Exception as e:
|
||||
log_cf2dns.logger.error("CHANGE DNS ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----MESSAGE: " + str(e))
|
||||
|
||||
def main(cloud):
|
||||
global AFFECT_NUM, TYPE
|
||||
if TYPE == 'v6':
|
||||
recordType = "AAAA"
|
||||
else:
|
||||
recordType = "A"
|
||||
if len(DOMAINS) > 0:
|
||||
try:
|
||||
cfips = get_optimization_ip()
|
||||
if cfips == None or cfips["code"] != 0:
|
||||
log_cf2dns.logger.error("GET CLOUDFLARE IP ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----MESSAGE: " + str(cfips["data"]))
|
||||
return
|
||||
cf_cmips = cfips["data"]["CM"]
|
||||
cf_cuips = cfips["data"]["CU"]
|
||||
cf_ctips = cfips["data"]["CT"]
|
||||
for domain, sub_domains in DOMAINS.items():
|
||||
for sub_domain, lines in sub_domains.items():
|
||||
#下面5个数组存的是不同线路最新获取的优选IP列表
|
||||
temp_cf_cmips = cf_cmips.copy()
|
||||
temp_cf_cuips = cf_cuips.copy()
|
||||
temp_cf_ctips = cf_ctips.copy()
|
||||
temp_cf_abips = cf_ctips.copy()
|
||||
temp_cf_defips = cf_ctips.copy()
|
||||
if DNS_SERVER == 1:
|
||||
ret = cloud.get_record(domain, 20, sub_domain, "CNAME")
|
||||
if ret["code"] == 0:
|
||||
for record in ret["data"]["records"]:
|
||||
if record["line"] == "移动" or record["line"] == "联通" or record["line"] == "电信":
|
||||
retMsg = cloud.del_record(domain, record["id"])
|
||||
if(retMsg["code"] == 0):
|
||||
log_cf2dns.logger.info("DELETE DNS SUCCESS: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+record["line"] )
|
||||
else:
|
||||
log_cf2dns.logger.error("DELETE DNS ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----DOMAIN: " + domain + "----SUBDOMAIN: " + sub_domain + "----RECORDLINE: "+record["line"] + "----MESSAGE: " + retMsg["message"] )
|
||||
ret = cloud.get_record(domain, 100, sub_domain, recordType)
|
||||
# ret["code"] == 0 就是DNS_SERVER == 1
|
||||
if DNS_SERVER != 1 or ret["code"] == 0 :
|
||||
if DNS_SERVER == 1 and "Free" in ret["data"]["domain"]["grade"] and AFFECT_NUM > 2:
|
||||
AFFECT_NUM = 2
|
||||
#下面5个数组存的是已存在的DNS解析列表
|
||||
cm_info = []
|
||||
cu_info = []
|
||||
ct_info = []
|
||||
ab_info = []
|
||||
def_info = []
|
||||
for record in ret["data"]["records"]:
|
||||
info = {}
|
||||
info["recordId"] = record["id"]
|
||||
info["value"] = record["value"]
|
||||
if record["line"] == "移动":
|
||||
cm_info.append(info)
|
||||
elif record["line"] == "联通":
|
||||
cu_info.append(info)
|
||||
elif record["line"] == "电信":
|
||||
ct_info.append(info)
|
||||
elif record["line"] == "境外":
|
||||
ab_info.append(info)
|
||||
elif record["line"] == "默认":
|
||||
def_info.append(info)
|
||||
for line in lines:
|
||||
if line == "CM":
|
||||
changeDNS("CM", cm_info, temp_cf_cmips, domain, sub_domain, cloud)
|
||||
elif line == "CU":
|
||||
changeDNS("CU", cu_info, temp_cf_cuips, domain, sub_domain, cloud)
|
||||
elif line == "CT":
|
||||
changeDNS("CT", ct_info, temp_cf_ctips, domain, sub_domain, cloud)
|
||||
elif line == "AB":
|
||||
changeDNS("AB", ab_info, temp_cf_abips, domain, sub_domain, cloud)
|
||||
elif line == "DEF":
|
||||
changeDNS("DEF", def_info, temp_cf_defips, domain, sub_domain, cloud)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
log_cf2dns.logger.error("CHANGE DNS ERROR: ----Time: " + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "----MESSAGE: " + str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if DNS_SERVER == 1:
|
||||
cloud = QcloudApiv3(SECRETID, SECRETKEY)
|
||||
elif DNS_SERVER == 2:
|
||||
cloud = AliApi(SECRETID, SECRETKEY, REGION_ALI)
|
||||
elif DNS_SERVER == 3:
|
||||
cloud = HuaWeiApi(SECRETID, SECRETKEY, REGION_HW)
|
||||
elif DNS_SERVER == 4:
|
||||
cloud = NameSiloClient(SECRETKEY)
|
||||
main(cloud)
|
||||
Reference in New Issue
Block a user