|
|
| """
|
| DNS-over-HTTPS resolver for HF Spaces.
|
|
|
| HF Spaces containers cannot resolve certain domains (e.g. web.whatsapp.com)
|
| via the default DNS resolver. This script resolves key domains using
|
| Cloudflare DoH (DNS-over-HTTPS) and writes results to a JSON file
|
| for the Node.js DNS fix script to consume.
|
|
|
| Usage: python3 dns-resolve.py [output-file]
|
| """
|
|
|
| import json
|
| import os
|
| import ssl
|
| import sys
|
| import urllib.request
|
|
|
| DOH_ENDPOINTS = [
|
| "https://1.1.1.1/dns-query",
|
| "https://8.8.8.8/resolve",
|
| "https://dns.google/resolve",
|
| ]
|
|
|
|
|
| DOMAINS = [
|
|
|
| "web.whatsapp.com",
|
| "g.whatsapp.net",
|
| "mmg.whatsapp.net",
|
| "pps.whatsapp.net",
|
| "static.whatsapp.net",
|
| "media.fmed1-1.fna.whatsapp.net",
|
|
|
| "api.telegram.org",
|
| ]
|
|
|
|
|
| def resolve_via_doh(domain: str, endpoint: str, timeout: int = 10) -> list[str]:
|
| """Resolve a domain via DNS-over-HTTPS, return list of IPv4 addresses."""
|
| url = f"{endpoint}?name={domain}&type=A"
|
| req = urllib.request.Request(url, headers={"Accept": "application/dns-json"})
|
|
|
| ctx = ssl.create_default_context()
|
| resp = urllib.request.urlopen(req, timeout=timeout, context=ctx)
|
| data = json.loads(resp.read().decode())
|
|
|
| ips = []
|
| for answer in data.get("Answer", []):
|
| if answer.get("type") == 1:
|
| ips.append(answer["data"])
|
| elif answer.get("type") == 5:
|
| continue
|
| return ips
|
|
|
|
|
| def resolve_domain(domain: str) -> list[str]:
|
| """Try multiple DoH endpoints until one succeeds."""
|
| for endpoint in DOH_ENDPOINTS:
|
| try:
|
| ips = resolve_via_doh(domain, endpoint)
|
| if ips:
|
| return ips
|
| except Exception:
|
| continue
|
| return []
|
|
|
|
|
| def main() -> None:
|
| output_file = sys.argv[1] if len(sys.argv) > 1 else "/tmp/dns-resolved.json"
|
|
|
|
|
| try:
|
| import socket
|
| socket.getaddrinfo("web.whatsapp.com", 443, socket.AF_INET)
|
| socket.getaddrinfo("api.telegram.org", 443, socket.AF_INET)
|
| print("[dns] System DNS works for WhatsApp & Telegram — DoH not needed")
|
|
|
| with open(output_file, "w") as f:
|
| json.dump({}, f)
|
| return
|
| except (socket.gaierror, OSError) as e:
|
| print(f"[dns] System DNS failed ({e}) — using DoH fallback")
|
|
|
| results = {}
|
| for domain in DOMAINS:
|
| ips = resolve_domain(domain)
|
| if ips:
|
| results[domain] = ips[0]
|
| print(f"[dns] {domain} -> {ips[0]}")
|
| else:
|
| print(f"[dns] WARNING: could not resolve {domain}")
|
|
|
| with open(output_file, "w") as f:
|
| json.dump(results, f, indent=2)
|
|
|
|
|
| if results:
|
| try:
|
| with open("/etc/hosts", "a") as f:
|
| f.write("\n# === HuggingClaw DoH resolved domains ===\n")
|
| for domain, ip in results.items():
|
| f.write(f"{ip} {domain}\n")
|
| print(f"[dns] Wrote {len(results)} entries to /etc/hosts")
|
| except PermissionError:
|
| print("[dns] WARNING: cannot write /etc/hosts (permission denied)")
|
|
|
| print(f"[dns] Resolved {len(results)}/{len(DOMAINS)} domains -> {output_file}")
|
|
|
|
|
| if __name__ == "__main__":
|
| main()
|
|
|