From ea62c6b396a0d019c702df86f9bf5610d3046186 Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Sun, 20 Apr 2025 23:22:25 +0200 Subject: [PATCH] initial commit --- README.md | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ec3385 --- /dev/null +++ b/README.md @@ -0,0 +1,139 @@ +# UpDNS + +A lightweight Go DynDNS‑proxy service that accepts authenticated update requests and forwards them to an upstream DDNS provider (e.g. Hetzner Cloud DNS). Fully pluggable so you can add new providers in future. + +## Features + +- HTTP API for dynamic DNS updates +- Per‑host API key (“secret”) authentication +- Client‑to‑domain mapping in a single YAML/JSON/TOML config +- Support for exact hostnames **and** wildcard domains (all subdomains) +- Configurable upstream DDNS (default: Hetzner Cloud DNS) +- Extensible provider interface for other DNS services +- Optional TLS support +- Logging & metrics + +## Quick Start + +1. **Install** + ```bash + go install git.cloonar.com/cloonar/updns@latest + ``` + +2. **Create a config file** (`config.yaml`): + + ```yaml + server: + bind_address: ":8080" + tls: + enabled: false + cert_file: "/path/to/cert.pem" + key_file: "/path/to/key.pem" + + upstream: + provider: hetzner + hetzner: + api_token: "YOUR_HETZNER_API_TOKEN" + + clients: + client1: + secret: "s3cr3t123" + # Allow updates only to exactly these hostnames: + exact: + - "home.example.com" + - "sub.example.org" + # Allow updates to this domain and all its subdomains: + wildcard: + - "example.net" + + client2: + secret: "otherSecret" + # Allow both an exact record and entire subdomain tree: + exact: + - "app.acme.io" + wildcard: + - "acme.io" + ``` + +3. **Run the proxy** + ```bash + updns --config config.yaml + ``` + +4. **Update DNS** + ```bash + curl -X POST https:///update \ + -H "Content-Type: application/json" \ + -d '{ + "key": "client1", + "secret": "s3cr3t123", + "host": "api.example.net", + "ip": "203.0.113.42" + }' + ``` + Since `client1` has `wildcard: ["example.net"]`, `api.example.net` is permitted. + Success returns: + ```json + { "status": "ok", "message": "Record updated" } + ``` + +## Configuration + +- **server.bind_address** – `host:port` to bind (default `:8080`) +- **server.tls.enabled** – enable HTTPS +- **upstream.provider** – one of `hetzner` (future: `cloudflare`, `aws`, etc) +- **upstream.** – provider‑specific credentials +- **clients** – mapping client IDs to: + - `secret` – HMAC/API key for authentication + - `exact` – list of fully qualified hostnames the client may update + - `wildcard` – list of base domains; any subdomain (including the base) is permitted + +> **Note:** +> - An exact entry like `home.example.com` allows only that specific record. +> - A wildcard entry like `example.com` allows updates to `example.com`, `www.example.com`, `foo.bar.example.com`, etc. + +## HTTP API + +### POST /update + +| Field | Type | Required | Description | +|----------|--------|----------|----------------------------------------| +| `key` | string | yes | Client identifier | +| `secret` | string | yes | Client’s secret for authentication | +| `host` | string | yes | Hostname to update (must match `exact` or fall under a `wildcard`) | +| `ip` | string | no | IPv4 or IPv6; defaults to caller’s IP | + +**Response** +- `200 OK` on success: + + ```json + { "status": "ok", "message": "Record updated" } + ``` + +- `4xx/5xx` on error: + + ```json + { "status": "error", "message": "Invalid secret or unauthorized host" } + ``` + +## Extending Providers + +1. Implement the `Provider` interface: + ```go + type Provider interface { + UpdateRecord(ctx context.Context, domain, ip string) error + } + ``` +2. Wire it up in `cmd/updns/main.go`’s provider factory. +3. Add config fields under `upstream.`. + +## Contributing + +1. Fork & clone this repo +2. `go mod tidy` +3. Write code, tests & update docs +4. Submit a PR + +## License + +MIT © 2025 Cloonar Technologies GmbH