From 2a7bd2c25029646e0bcfc5eaa0881ba00b643741 Mon Sep 17 00:00:00 2001 From: devaine Date: Sun, 10 Aug 2025 17:20:10 -0500 Subject: [PATCH] feat(server): added a new server script for desec, updates all dns' --- .gitignore | 1 + server-scripts/desec/desec.py | 101 ++++++++++++++++++++++++++++++++++ server-scripts/desec/dev.bash | 11 ++++ server-scripts/desec/run.bash | 7 +++ 4 files changed, 120 insertions(+) create mode 100755 server-scripts/desec/desec.py create mode 100755 server-scripts/desec/dev.bash create mode 100755 server-scripts/desec/run.bash diff --git a/.gitignore b/.gitignore index e69de29..4c49bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/server-scripts/desec/desec.py b/server-scripts/desec/desec.py new file mode 100755 index 0000000..78f5fa6 --- /dev/null +++ b/server-scripts/desec/desec.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +import subprocess +import json +import os +import asyncio +from dotenv import load_dotenv + +load_dotenv() # Loads up .env file + +current_domain = os.getenv("CURRENT_DOMAIN") +desec_token = os.getenv("DESEC_TOKEN") +excluded_subdomains = ["mail._domainkey.mail", "mail", "_dmarc.mail"] +timeout = 1800 # In seconds, 600 = 10min, 900 = 15m, 1800 = 30min + +# Credits: +# https://desec.readthedocs.io/en/latest/dns/rrsets.html#modifying-an-rrset +# for documentation + + +async def modifyRecords(newIP): + args = "curl https://desec.io/api/v1/domains/" + current_domain + \ + "/rrsets/ --header 'Authorization: Token " + desec_token + "'" + + data_binary = subprocess.run( + args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) + data = data_binary.stdout.decode("utf-8") + + # convert to python object from str + json_data = json.loads(data) + + for i in range(len(excluded_subdomains)): + excluded_subdomains[i] = excluded_subdomains[i] + \ + "." + current_domain + "." + + for entry in json_data: + # Only allow "A" record subdomains at the moment + if entry["name"] not in excluded_subdomains and entry["type"] == "A": + if (entry["records"][0] != newIP): + subname = str(entry["subname"]) # Subdomain Name + + # Basically runs a PATCH method for the api to change + # the ip record of all "A" record subdomains to the new + # public ip address + + change_record_arg = \ + "curl -X PATCH https://desec.io/api/v1/domains/" + \ + current_domain + "/rrsets/" + subname + \ + "/A/" + " --header 'Authorization: Token " \ + + desec_token + "'" + " --header " + \ + "'Content-Type: application/json' " + \ + "--data @- <<< '{\"records\": [\"" + newIP + "\"] }'" + + # print(change_record_arg) + subprocess.run(change_record_arg, shell=True) + await asyncio.sleep(5) + + print("done with changing records!") + + +def getCurrentIP(): + print("getting current ip...") + + # Get the current Public IP to a "public_ip" file + subprocess.run( + ["curl", "ifconfig.me", "-o", "public_ip"], stderr=subprocess.DEVNULL) + + +async def newIPCheck(): + print("checking for new ips...") + presentIPFile = open("public_ip", "r") + + newIP_curl = subprocess.run(["curl", "ifconfig.me"], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + + newIP = newIP_curl.stdout.decode("utf-8") + + if (presentIPFile.readline() == newIP): + await asyncio.sleep(timeout) + await newIPCheck() + + else: + print("uh oh! public ip updated!") + await modifyRecords(newIP) + getCurrentIP() # update current ip + await newIPCheck() + + +def main(): + if not os.path.exists("public_ip"): + getCurrentIP() + elif not os.path.exists(".env"): + print("no visible .env file for token!") + exit(1) + + asyncio.run(newIPCheck()) + + +if __name__ == "__main__": + main() diff --git a/server-scripts/desec/dev.bash b/server-scripts/desec/dev.bash new file mode 100755 index 0000000..be6b92f --- /dev/null +++ b/server-scripts/desec/dev.bash @@ -0,0 +1,11 @@ +#!/bin/bash + +# If virtual environment does exist.. +if [ ! -d .venv ]; then + python3 -m venv .venv + source .venv/bin/activate + pip install -U python-dotenv + pip install --upgrade pip # Update pip to the latest version +fi + +echo 'Make sure to run ". .venv/bin/activate" to enter the development environment' diff --git a/server-scripts/desec/run.bash b/server-scripts/desec/run.bash new file mode 100755 index 0000000..4c833f9 --- /dev/null +++ b/server-scripts/desec/run.bash @@ -0,0 +1,7 @@ +#!/bin/bash + +cd /home/user/scripts/desec + +. .venv/bin/activate + +./desec.py