First Commit

This commit is contained in:
Bigsk 2022-06-04 19:25:08 +08:00
parent 058045ec95
commit c7a1fb4141
3 changed files with 409 additions and 0 deletions

283
ntp_daemon.py Normal file
View File

@ -0,0 +1,283 @@
import socket, struct, threading, time, json, logging
# flask, requests
import flask, requests
RECORD_UPDATE_SWITCH = True
API_LISTEN = ("0.0.0.0", 5000)
INTERVAL = 60 * 60
DOMAIN = ""
A_ID = ""
A_KEY = ""
app = flask.Flask("NTP")
log = logging.getLogger('werkzeug')
log.disabled = True
if RECORD_UPDATE_SWITCH:
# alibabacloud_alidns20150109==2.0.2
from alibabacloud_alidns20150109.client import Client as Alidns20150109Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_alidns20150109 import models as alidns_20150109_models
from alibabacloud_tea_util import models as util_models
class Domain:
def __init__(self):
pass
@staticmethod
def create_client(
access_key_id: str,
access_key_secret: str,
) -> Alidns20150109Client:
config = open_api_models.Config(
access_key_id=access_key_id,
access_key_secret=access_key_secret
)
config.endpoint = f'alidns.cn-hangzhou.aliyuncs.com'
return Alidns20150109Client(config)
@staticmethod
def get_records():
client = Domain.create_client(A_ID, A_KEY)
describe_domain_records_request = alidns_20150109_models.DescribeDomainRecordsRequest(
domain_name=DOMAIN
)
runtime = util_models.RuntimeOptions()
try:
return True, eval(str(client.describe_domain_records_with_options(describe_domain_records_request, runtime)))["body"]["DomainRecords"]["Record"]
except Exception as error:
return False, error
@staticmethod
def delete_record(rr) -> None:
client = Domain.create_client(A_ID, A_KEY)
delete_sub_domain_records_request = alidns_20150109_models.DeleteSubDomainRecordsRequest(
domain_name=DOMAIN,
rr=rr
)
runtime = util_models.RuntimeOptions()
try:
return True, eval(str(client.describe_domain_records_with_options(client.delete_sub_domain_records_with_options(delete_sub_domain_records_request, runtime))))
except Exception as error:
return False, error
@staticmethod
def add_record(rr, type, value, line) -> None:
client = Domain.create_client(A_ID, A_KEY)
add_domain_record_request = alidns_20150109_models.AddDomainRecordRequest(
domain_name=DOMAIN,
rr=rr,
type=type,
value=value,
line=line
)
runtime = util_models.RuntimeOptions()
try:
return True, eval(str(client.add_domain_record_with_options(add_domain_record_request, runtime)))
except Exception as error:
return False, error
def is_ipv4(ip):
try:
socket.inet_pton(socket.AF_INET, ip)
except AttributeError:
try:
socket.inet_aton(ip)
except socket.error:
return False
return ip.count('.') == 3
except socket.error:
return False
return True
def is_ipv6(ip):
try:
socket.inet_pton(socket.AF_INET6, ip)
except socket.error:
return False
return True
def ip_type(ip):
if is_ipv4(ip) and not is_ipv6(ip):
return 4
elif is_ipv6(ip) and not is_ipv4(ip):
return 6
else:
return 0
def ip_area(ip):
type = ip_type(ip)
if type == 4 or type == 6:
info = requests.get(f"https://api.ghink.net/ip/zh_cn/v{type}/{ip}").json()
if info["code"] != 20000:
return "default"
info = info["content"]
if type == 4:
if info["pro"] == "":
return "oversea"
elif "教育" in info["addr"] or "学院" in info["addr"] or "大学" in info["addr"]:
return "edu"
elif "电信" in info["addr"]:
return "telecom"
elif "移动" in info["addr"] or "移通" in info["addr"]:
return "mobile"
elif "联通" in info["addr"]:
return "unicom"
else:
return "default"
elif type == 6:
if info["pro"] == "" and info["city"] == "":
return "oversea"
elif "教育" in info["addr"] or "学院" in info["addr"] or "大学" in info["addr"]:
return "edu"
elif "电信" in info["addr"]:
return "telecom"
elif "移动" in info["addr"] or "移通" in info["addr"]:
return "mobile"
elif "联通" in info["addr"]:
return "unicom"
else:
return "default"
else:
return "default"
def ntp(server):
type = ip_type(server)
if type == 4:
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
elif type == 6:
client = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
else:
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
data = ("\x1b" + 47 * "\0").encode()
try:
client.sendto(data, (server, 123))
except socket.gaierror:
return False
data, address = client.recvfrom(1024)
if data:
t = struct.unpack('!12I', data)[10]
t -= 2208988800
return t
else:
return False
def check(server):
global active
if ntp(server):
if server not in active:
active.append(server)
else:
if server in active:
del active[active.index(server)]
def update_status():
global active, servers
# Read Server Pool
servers = []
with open("pool.txt", "r") as fb:
servers = [s.strip() for s in fb.readlines()]
# Duplicate Removal
temp = []
for s in servers:
if s not in temp:
temp.append(s)
servers = temp
with open("pool.txt", "w+") as fb:
for s in servers:
fb.write(f"{s}\n")
# Check
for s in active:
thread = threading.Thread(target=check, args=(s, ), name=s)
thread.start()
thread.join(1)
with open("pool.txt", "r") as fb:
for line in fb.readlines():
thread = threading.Thread(target=check, args=(line.strip(), ), name=line.strip())
thread.start()
thread.join(1)
def update_status_daemon():
while True:
update_status()
time.sleep(INTERVAL)
def update_records():
ok, records = Domain.get_records()
if ok:
for r in records:
if r["Value"] not in servers:
ok, msg = Domain.delete_record(r["Value"])
if not ok:
print(msg)
for s in active:
flag = True
for r in records:
if r["Value"] == s:
flag = False
if flag:
ok, msg = Domain.add_record("@", "A" if ip_type(s) == 4 else "AAAA", s, ip_area(s))
if not ok and "The maximum number of 10 records is exceeded" not in str(msg) and "The DNS record already exists." not in str(msg):
print(msg)
else:
print(records)
def update_records_daemon():
while True:
update_records()
time.sleep(10)
@app.route("/update")
def update_api():
update_thread = threading.Thread(target=update_status, name="Update From API For Status")
update_thread.daemon = True
update_thread.start()
if RECORD_UPDATE_SWITCH:
update_thread = threading.Thread(target=update_records, name="Update From API For Records")
update_thread.daemon = True
update_thread.start()
return json.dumps(
{
"message": "Success",
"content": None
}
), 200, {"content-type": "application/json"}
@app.route("/list")
def list_api():
return json.dumps(
{
"message": "Success",
"content": active
}
), 200, {"content-type": "application/json"}
if __name__ == '__main__':
active = []
servers = []
update_status_daemon_thread = threading.Thread(target=update_status_daemon, name="Update Daemon For Status")
update_status_daemon_thread.daemon = True
update_status_daemon_thread.start()
if RECORD_UPDATE_SWITCH:
update_status_daemon_thread = threading.Thread(target=update_records_daemon, name="Update Daemon For Records")
update_status_daemon_thread.daemon = True
update_status_daemon_thread.start()
api_daemon = threading.Thread(target=app.run, args=API_LISTEN, name="API Daemon")
api_daemon.daemon = True
api_daemon.start()
while True:
if input() == "exit":
break
print(f"Report {time.ctime(time.time())}:")
print(f"{len(active)} Servers Active, They are:")
for i in range(len(active)):
if not (i+1) % 5:
print(active[i])
else:
print(active[i], end=" ")
print("", end="" if not len(active) % 5 or not len(active) else "\n")

123
pool.txt Normal file
View File

@ -0,0 +1,123 @@
103.11.143.248
120.25.115.20
116.13.10.10
203.107.6.88
202.112.29.82
120.25.108.11
182.92.12.11
85.199.214.100
101.6.6.172
216.218.254.202
66.228.42.59
211.233.40.78
158.69.48.97
203.114.74.17
2402:f000:1:416:101:6:6:172
2001:250:380A:5::10
2001:da8:9000::81
2001:da8:9000::130
185.209.85.222
94.130.49.186
84.16.67.12
78.46.102.180
193.182.111.143
202.118.1.81
108.59.2.24
94.237.64.20
219.216.128.25
119.28.183.184
162.159.200.123
111.230.189.174
178.215.228.24
119.28.206.193
193.182.111.12
193.182.111.142
45.77.144.44
167.172.70.21
192.33.214.47
171.66.97.126
213.206.184.75
104.194.8.227
69.197.128.202
178.63.9.212
135.125.169.44
61.239.100.196
45.125.1.20
142.147.88.111
149.202.91.39
147.182.158.78
185.216.231.84
161.53.78.71
152.115.59.242
192.48.105.15
95.215.175.2
103.147.22.149
168.61.215.74
129.250.35.251
128.4.24.98
202.118.1.130
129.250.35.250
95.216.192.15
133.243.238.243
103.104.28.105
45.132.84.104
103.13.114.65
203.99.62.214
161.200.192.4
58.176.194.96
162.159.200.1
202.12.97.45
110.170.126.102
121.174.142.81
17.253.116.253
202.28.93.5
194.0.5.123
80.241.0.72
192.46.210.39
139.199.214.202
203.147.59.17
23.106.249.200
202.28.116.236
13.209.84.50
203.131.222.11
212.138.72.43
17.253.84.253
212.138.72.41
95.216.144.226
64.227.167.110
202.21.176.62
202.65.114.202
103.38.215.205
212.26.18.43
203.113.174.44
36.91.114.86
223.113.120.195
223.113.97.98
223.65.211.46
36.154.179.82
223.113.103.191
58.220.133.132
114.67.237.130
114.67.103.73
140.143.99.185
111.230.50.201
106.75.185.63
119.29.26.206
120.197.116.202
202.112.31.197
149.129.123.30
106.186.122.232
106.187.100.179
133.100.11.8
106.247.248.106
202.73.57.107
128.199.134.40
218.186.3.36
188.166.245.58
208.53.158.34
131.188.3.220
131.188.3.223
166.111.8.28
166.111.8.29
2402:f000:1:801::8:28
2402:f000:1:801::8:29

3
requirement.txt Normal file
View File

@ -0,0 +1,3 @@
flask
alibabacloud_alidns20150109==2.0.2
requests