diff --git a/ddns.py b/ddns.py new file mode 100644 index 0000000..1c3365a --- /dev/null +++ b/ddns.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""DDNS updater — keep the proxy hostname pointed at the home WAN IP. + +The SOCKS5/HTTP gateway is exposed on the home WAN IP (dynamic Comcast). The +storefront advertises proxy.clean-proxys.thetempleofdoom.com instead of the raw +IP; this updater keeps that A record in sync. DNS-only (proxied=false) because +Cloudflare's orange-cloud cannot carry raw TCP (SOCKS5/HTTP CONNECT). + +Runs on CT777 (egresses via the home WAN, so ipify returns the real home IP — +NOT the MacBook's Nord egress). Scheduled by ddns.timer every 15 min. +""" +import json + +import requests + +CFG = json.load(open("/opt/pleiades/config.json")) +CF = CFG["cloudflare"] + +API = "https://api.cloudflare.com/client/v4" +HDR = {"X-Auth-Email": CF["email"], "X-Auth-Key": CF["api_key"], + "Content-Type": "application/json"} + + +def get_wan_ip(): + r = requests.get("https://api.ipify.org", timeout=10) + r.raise_for_status() + return r.text.strip() + + +def find_record(): + r = requests.get(f"{API}/zones/{CF['zone_id']}/dns_records", + params={"name": CF["record_name"], "type": "A"}, + headers=HDR, timeout=15) + r.raise_for_status() + recs = r.json().get("result", []) + return recs[0] if recs else None + + +def main(): + wan = get_wan_ip() + rec = find_record() + body = {"type": "A", "name": CF["record_name"], "content": wan, + "ttl": 120, "proxied": False} + if rec is None: + r = requests.post(f"{API}/zones/{CF['zone_id']}/dns_records", + headers=HDR, json=body, timeout=15) + ok = r.json().get("success") + print(f"created {CF['record_name']} -> {wan} (success={ok})") + return + cur = rec.get("content") + if cur == wan: + print(f"no change: {CF['record_name']} -> {wan}") + return + r = requests.put(f"{API}/zones/{CF['zone_id']}/dns_records/{rec['id']}", + headers=HDR, json=body, timeout=15) + ok = r.json().get("success") + print(f"updated {CF['record_name']}: {cur} -> {wan} (success={ok})") + + +if __name__ == "__main__": + main() diff --git a/ddns.service b/ddns.service new file mode 100644 index 0000000..5336a70 --- /dev/null +++ b/ddns.service @@ -0,0 +1,8 @@ +[Unit] +Description=Clean Proxys DDNS updater (one-shot) +After=network-online.target + +[Service] +Type=oneshot +WorkingDirectory=/opt/pleiades +ExecStart=/usr/bin/python3 /opt/pleiades/ddns.py diff --git a/ddns.timer b/ddns.timer new file mode 100644 index 0000000..d643f3c --- /dev/null +++ b/ddns.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Clean Proxys DDNS updater (every 15 min) + +[Timer] +OnBootSec=60s +OnUnitActiveSec=15min +Unit=ddns.service + +[Install] +WantedBy=timers.target