Files
setec_cdm/setec-web/dns_client.py
DigiJ 9e839ee826 Initial commit — SETEC LABS Manager (Setec_CDM)
Flask-based VPS management panel with SSH remote command execution.
Includes E2E encrypted SSH tunnel (AES-256-GCM + Go agent), setup wizard,
security hardening tools, DNS management, firewall configs, monitoring,
backup, and .sec patch update system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:39:02 -07:00

111 lines
3.5 KiB
Python

import requests
import ssh_client
import config
BASE = "https://api.hostinger.com/api/dns/v1/zones"
def _headers():
cfg = config.load()
return {
"Authorization": f"Bearer {cfg['hostinger_api_key']}",
"Content-Type": "application/json",
}
def _domain():
return config.load()["domain"]
def get_records():
"""Try Hostinger API first (via VPS to avoid Cloudflare), fall back to dig."""
cfg = config.load()
key = cfg.get("hostinger_api_key", "")
domain = cfg["domain"]
# Try API via VPS
try:
cmd = (
f"curl -s -w '\\nHTTP_CODE:%{{http_code}}' "
f"-H 'Authorization: Bearer {key}' "
f"-H 'Content-Type: application/json' "
f"'https://api.hostinger.com/api/dns/v1/zones/{domain}' 2>&1"
)
result = ssh_client.run(cmd, timeout=15)
output = result["stdout"]
if "HTTP_CODE:200" in output:
import json
body = output.rsplit("\nHTTP_CODE:", 1)[0]
return json.loads(body)
except Exception:
pass
# Try direct from local
try:
r = requests.get(f"{BASE}/{domain}", headers=_headers(), timeout=15)
if r.status_code == 200:
return r.json()
except Exception:
pass
# Fallback: use dig to show current DNS records
result = ssh_client.run(
f"echo '=== A Records ===' && dig +short A {domain} && "
f"echo '=== CNAME ===' && dig +short CNAME {domain} && "
f"echo '=== MX ===' && dig +short MX {domain} && "
f"echo '=== TXT ===' && dig +short TXT {domain} && "
f"echo '=== NS ===' && dig +short NS {domain} && "
f"echo '=== Subdomains ===' && "
f"for sub in repo git app files lists mail www; do "
f" ip=$(dig +short A $sub.{domain}); "
f" [ -n \"$ip\" ] && echo \"$sub.{domain} -> $ip\"; "
f"done",
timeout=15,
)
return {"source": "dig (API unavailable)", "records": result["stdout"]}
def add_a_record(name, ip, ttl=14400):
cfg = config.load()
key = cfg.get("hostinger_api_key", "")
domain = cfg["domain"]
payload = f'{{"records":[{{"name":"{name}","type":"A","content":"{ip}","ttl":{ttl}}}],"overwrite":false}}'
result = ssh_client.run(
f"curl -s -w '\\nHTTP_CODE:%{{http_code}}' -X PUT "
f"-H 'Authorization: Bearer {key}' "
f"-H 'Content-Type: application/json' "
f"-d '{payload}' "
f"'https://api.hostinger.com/api/dns/v1/zones/{domain}' 2>&1",
timeout=15,
)
return {"response": result["stdout"]}
def add_txt_record(name, value, ttl=14400):
cfg = config.load()
key = cfg.get("hostinger_api_key", "")
domain = cfg["domain"]
payload = f'{{"records":[{{"name":"{name}","type":"TXT","content":"{value}","ttl":{ttl}}}],"overwrite":false}}'
result = ssh_client.run(
f"curl -s -w '\\nHTTP_CODE:%{{http_code}}' -X PUT "
f"-H 'Authorization: Bearer {key}' "
f"-H 'Content-Type: application/json' "
f"-d '{payload}' "
f"'https://api.hostinger.com/api/dns/v1/zones/{domain}' 2>&1",
timeout=15,
)
return {"response": result["stdout"]}
def delete_record(record_id):
cfg = config.load()
key = cfg.get("hostinger_api_key", "")
domain = cfg["domain"]
result = ssh_client.run(
f"curl -s -w '\\nHTTP_CODE:%{{http_code}}' -X DELETE "
f"-H 'Authorization: Bearer {key}' "
f"'https://api.hostinger.com/api/dns/v1/zones/{domain}/records/{record_id}' 2>&1",
timeout=15,
)
return {"response": result["stdout"]}