commit 529586caae577e07cd50bfa4cec785afe68b7b04 Author: Morgan Date: Sun May 28 12:24:47 2023 +0900 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6b6498 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +secrets.py \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/cfddns-server.py b/cfddns-server.py new file mode 100644 index 0000000..37e08d3 --- /dev/null +++ b/cfddns-server.py @@ -0,0 +1,45 @@ +from fastapi import FastAPI, Request +import cfddns +import requests +import secrets + +app = FastAPI() + +def cloudflare(ip, domain): + return cfddns.update_dns(domain, ip) + +def njalla(ip, domain, key = None): + if not key: + return 0 + return requests.get(f"https://njal.la/update/?h={domain}&k={key}&a={ip}").text + +def route_ddns(provider, sub, domain, ip, sk = None): + if provider not in ddns_func: + return 0 + return ddns_func[provider](ip, domain, sk) + +ddns_func = {"cloudflare": cloudflare, + "njalla": njalla} + +@app.get ("/update") +async def ddns ( request: Request, sub: str, a: str | None = None, k: str | None = None, auto: bool | None = None, sk: str | None = None ): + print(f"Request from {request.client.host} with [ sub: {sub}, a: {a}, k: {k}, auto: {auto}, sk: {sk} ]") + + if k not in key_dict.values(): + return "Error: Key not authorized" + + for i in key_dict: + if key_dict[i] == k: + domain = i + break + + if auto: + ip = request.client.host + result = route_ddns(sub, domain, ip, sk) + else: + result = route_ddns(sub, domain, a, sk) + + if not result: + return "Error" + else: + return result \ No newline at end of file diff --git a/cfddns.py b/cfddns.py new file mode 100644 index 0000000..d5005cf --- /dev/null +++ b/cfddns.py @@ -0,0 +1,99 @@ +import requests, json +import socket +import secrets + +CF_GLOBAL_KEY = secrets.cloudflare.global_key +CF_API_KEY = secrets.cloudflare.api_key +CF_EMAIL = secrets.cloudflare.email +zone_id = secrets.cloudflare.zone_id + +auth = { + "X-Auth-Email": CF_EMAIL, + "X-Auth-Key": CF_GLOBAL_KEY, + "Content-Type": "application/json" +} + +def check_available(domain): + base_domian = ".".join(domain.split(".")[-2:]) + print(base_domian) + + if base_domian in zone_id.keys(): + return base_domian + else: + return 0 + +def update_dns(domain, new_ip): + base_domian = check_available(domain) + assert base_domian + print(domain) + zid = zone_id[base_domian] + list_api = f"https://api.cloudflare.com/client/v4/zones/{zid}/dns_records?name=" + edit_api = f"https://api.cloudflare.com/client/v4/zones/{zid}/dns_records" + dns_info = {"type": "A", "name": domain, "ttl": 3600, "proxied": False} + + check_domain(zid, domain, new_ip) + + try: + old_ip = socket.gethostbyname(dns_info["name"]) + except: + old_ip = None + + if old_ip == new_ip: + print(f"No change. {dns_info['name']}: {old_ip}") + return 0 + + else: + dns_res_txt = requests.get(f"{list_api}{domain}", headers=auth).text + print(dns_res_txt) + dns_id = json.loads(dns_res_txt)["result"][0]["id"] + dns_info["content"] = new_ip + upd = requests.put(f"{edit_api}/{dns_id}", headers=auth, data=json.dumps(dns_info)).text + + try: + upd = json.loads(upd) + except: + print(upd) + + dn_name = upd["result"]["name"] + dn_type = upd["result"]["type"] + dn_content = upd["result"]["content"] + + print(f"DNS record updated to {dn_type}: {dn_name} = {dn_content}") + return f"Success: {dn_name} updated to {dn_content}" + +def check_domain(zid, domain, ip = None): + existing = [ i["name"] for i in list_domains(zid)] + print(existing, domain) + + if domain not in existing: + create_record(domain, zid, ip) + +def create_record(sub, zid, ip = "1.1.1.1", record = "A"): + print(f"create_record({sub}, {zid}, {ip}, {record})") + api_url = f"https://api.cloudflare.com/client/v4/zones/{zid}/dns_records" + data = { + "content": ip, + "name": sub, + "proxied": False, + "type": record, + "comment": "", + "ttl": 3600 + } + res_txt = requests.post(api_url, headers=auth, data=json.dumps(data)).text + print(res_txt) + return res_txt + +def list_domains(zid): + api_url = f"https://api.cloudflare.com/client/v4/zones/{zid}/dns_records" + return json.loads(requests.get(api_url, headers=auth).text)["result"] + +if __name__=="__main__": + if len(sys.argv) not in [3, 2]: + print("cfddns.py [domain] (ip)") + this_domain = sys.argv[2] + if len(sys.argv) == 2: + this_ip = json.loads(requests.get("https://ip4.seeip.org/json").text)["ip"] + else: + this_ip = sys.argv[3] + print(this_ip, this_domain) + update_dns(this_domain, this_ip)