dns/server.py
2025-05-21 03:06:33 +00:00

81 lines
3.4 KiB
Python

import os
import gradio
import fastapi
import uvicorn
from dns import AliyunDNS
# Aliyun DNS 相关配置
DOMAIN_NAMES = str(os.getenv("DOMAIN_NAMES", "")).split(",")
BASE_URL = str(os.getenv("BASE_URL", "http://alidns.aliyuncs.com"))
ACCESS_KEY_ID = str(os.getenv("ACCESS_KEY_ID", ""))
ACCESS_KEY_SECRET = str(os.getenv("ACCESS_KEY_SECRET", ""))
# gradio 管理页面 相关配置
USERNAME = str(os.getenv("USERNAME", "admin"))
PASSWORD = str(os.getenv("PASSWORD", "password"))
SERVER_HOST = str(os.getenv("SERVER_HOST", "0.0.0.0"))
SERVER_PORT = int(os.getenv("SERVER_PORT", "60000"))
class Server:
def __init__(self):
self.aliyun_dns = AliyunDNS(BASE_URL, ACCESS_KEY_ID, ACCESS_KEY_SECRET)
self.resolutions = {domain_name: list() for domain_name in DOMAIN_NAMES}
def domain(self, domain):
self.resolutions[domain].clear()
records = self.aliyun_dns.DescribeDomainRecords(DomainName=domain)
for record in records["DomainRecords"]["Record"]:
self.resolutions[domain].append(
[record["RR"], record["Value"], record["RecordId"]])
self.resolutions[domain] = sorted(self.resolutions[domain], key=lambda x: x[0])
def webui(self, app, path):
with gradio.Blocks() as webui:
domain = gradio.Dropdown(label="主域名", choices=DOMAIN_NAMES, value=None)
editor = gradio.DataFrame(label="编辑解析信息", headers=["子域名", "解析地址", "记录编码"],
row_count=100, col_count=(3, "fixed"), datatype=["str", "str", "str"], type="pandas")
update = gradio.Button(value="更新解析信息")
@domain.select(inputs=[domain], outputs=[editor])
def _(domain):
domain = str(domain)
self.domain(domain=domain) # 更新解析信息
return self.resolutions[domain]
@update.click(inputs=[domain, editor], outputs=[editor])
def _(domain, editor):
domain = str(domain)
editor = [line for line in editor.values.tolist() if "".join(line) != ""] # 去除空行
last = {tuple(line) for line in self.resolutions[domain]}
now = {tuple(line) for line in editor}
for rr, ip, id in (now - last):
if rr == "" or ip == "": continue # 子域名或解析地址为空则不做解析
print(f"创建解析:{domain} {rr} {ip}")
self.aliyun_dns.AddDomainRecord(DomainName=domain, RR=rr, Type="A", Value=ip, Line="default", TTL=600)
for rr, ip, id in (last - now):
print(f"删除解析:{domain} {rr} {ip} {id}")
self.aliyun_dns.DeleteDomainRecord(RecordId=id)
self.domain(domain=domain) # 更新解析信息
return self.resolutions[domain]
gradio.mount_gradio_app(app, webui, path=path, auth=(USERNAME, PASSWORD))
def run(self, SERVER_HOST, SERVER_PORT):
app = fastapi.FastAPI()
self.webui(app=app, path="/")
uvicorn.run(app, host=SERVER_HOST, port=int(SERVER_PORT))
if __name__ == "__main__":
server = Server()
server.run(
SERVER_HOST=SERVER_HOST,
SERVER_PORT=SERVER_PORT
)