Initial commit: DDNS service with NIC V2 protocol support
Features: - Token-based subdomain claiming - NIC V2 (DynDNS2) protocol implementation - Technitium DNS integration - Rate limiting (10 req/min IP, 1 req/min token) - Web UI for space claiming - Docker/Docker Compose support - Compatible with UniFi, pfSense, EdgeRouter Module: git.dws.rip/DWS/dyn
This commit is contained in:
203
README.md
Normal file
203
README.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# DWS Dynamic DNS Service
|
||||
|
||||
A self-hosted Dynamic DNS (DDNS) provider built with Go, featuring a minimalist web UI and NIC V2 (DynDNS2) protocol support for router compatibility.
|
||||
|
||||
## Overview
|
||||
|
||||
This service allows users to claim subdomains under `space.dws.rip` and update them via the standard DynDNS2 protocol, compatible with UniFi, pfSense, EdgeRouters, and other consumer routers.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
|
||||
│ Router │ ──────► │ DWS Bridge │ ──────► │ Technitium DNS │
|
||||
│ (DynDNS2) │ HTTP │ (Go) │ API │ (Authoritative)│
|
||||
└─────────────┘ └──────────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ SQLite │
|
||||
│ (token→sub) │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Token-based authentication** - No user accounts, just secure tokens
|
||||
- **NIC V2 Protocol** - Compatible with most routers
|
||||
- **Automatic wildcard records** - `*.your-space.space.dws.rip` also works
|
||||
- **Rate limiting** - 10 req/min per IP, 1 req/min per token
|
||||
- **Clean web UI** - Simple space claiming interface
|
||||
- **Router config examples** - UniFi, pfSense, cURL snippets
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker and Docker Compose
|
||||
- Running Technitium DNS server with API access
|
||||
- DNS delegation for `space.dws.rip` pointing to Technitium
|
||||
|
||||
### DNS Setup
|
||||
|
||||
In your parent `dws.rip` zone:
|
||||
|
||||
```text
|
||||
space.dws.rip. IN NS dns.dws.rip.
|
||||
dns.dws.rip. IN A <TECHNITIUM_IP>
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Create a `.env` file:
|
||||
|
||||
```bash
|
||||
# Required: Technitium DNS API endpoint
|
||||
TECHNITIUM_URL=https://dns.dws.rip
|
||||
|
||||
# Authentication (choose one method)
|
||||
# Method 1: API Token (recommended)
|
||||
TECHNITIUM_TOKEN=your-api-token-here
|
||||
|
||||
# Method 2: Username/Password
|
||||
TECHNITIUM_USERNAME=admin
|
||||
TECHNITIUM_PASSWORD=your-password
|
||||
|
||||
# Optional: Domain configuration
|
||||
BASE_DOMAIN=dws.rip
|
||||
SPACE_SUBDOMAIN=space
|
||||
|
||||
# Optional: Rate limiting
|
||||
RATE_LIMIT_PER_IP=10
|
||||
RATE_LIMIT_PER_TOKEN=1
|
||||
|
||||
# Optional: Trusted proxies (comma-separated)
|
||||
TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
```bash
|
||||
# Clone and start
|
||||
git clone <repo>
|
||||
cd dyn
|
||||
docker-compose up -d
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Stop
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Web UI
|
||||
- `GET /` - Claim space interface
|
||||
|
||||
### API
|
||||
- `GET /api/check?subdomain=<name>` - Check subdomain availability
|
||||
- `POST /api/claim` - Claim a subdomain (returns token once)
|
||||
|
||||
### DynDNS2 Protocol
|
||||
- `GET /api/nic/update?hostname=<fqdn>&myip=<ip>`
|
||||
- Auth: Basic auth with username `none` and password = token
|
||||
- Returns: `good <ip>`, `nochg <ip>`, `badauth`, `nohost`, `911`
|
||||
|
||||
## Router Configuration
|
||||
|
||||
### UniFi / UDM
|
||||
|
||||
```
|
||||
Service: dyndns
|
||||
Hostname: your-space.space.dws.rip
|
||||
Username: none
|
||||
Password: <your-token>
|
||||
Server: dyn.dws.rip/api/nic/update
|
||||
```
|
||||
|
||||
### pfSense / OPNsense
|
||||
|
||||
```
|
||||
Service Type: Custom
|
||||
Update URL: https://dyn.dws.rip/api/nic/update?hostname=%h&myip=%i
|
||||
Username: none
|
||||
Password: <your-token>
|
||||
```
|
||||
|
||||
### EdgeRouter
|
||||
|
||||
```bash
|
||||
set service dns dynamic interface eth0 service custom-dyn host-name your-space.space.dws.rip
|
||||
set service dns dynamic interface eth0 service custom-dyn login none
|
||||
set service dns dynamic interface eth0 service custom-dyn password <your-token>
|
||||
set service dns dynamic interface eth0 service custom-dyn protocol dyndns2
|
||||
set service dns dynamic interface eth0 service custom-dyn server dyn.dws.rip
|
||||
```
|
||||
|
||||
### Manual (cURL)
|
||||
|
||||
```bash
|
||||
curl -u "none:<your-token>" \
|
||||
"https://dyn.dws.rip/api/nic/update?hostname=your-space.space.dws.rip&myip=1.2.3.4"
|
||||
```
|
||||
|
||||
## Database Schema
|
||||
|
||||
```sql
|
||||
CREATE TABLE spaces (
|
||||
token TEXT PRIMARY KEY,
|
||||
subdomain TEXT UNIQUE NOT NULL,
|
||||
last_ip TEXT,
|
||||
updated_at DATETIME,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
- **32-byte random tokens** - Generated with `crypto/rand`
|
||||
- **Token displayed once** - No recovery mechanism (claim new space if lost)
|
||||
- **Rate limiting** - Prevents brute force and abuse
|
||||
- **No PII stored** - Just token-to-subdomain mapping
|
||||
- **Input validation** - Subdomains validated (alphanumeric + hyphen only)
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `TECHNITIUM_URL` | Yes | - | Technitium API URL |
|
||||
| `TECHNITIUM_TOKEN` | No* | - | API token for auth |
|
||||
| `TECHNITIUM_USERNAME` | No* | - | Basic auth username |
|
||||
| `TECHNITIUM_PASSWORD` | No* | - | Basic auth password |
|
||||
| `BASE_DOMAIN` | No | `dws.rip` | Root domain |
|
||||
| `SPACE_SUBDOMAIN` | No | `space` | Subdomain for user spaces |
|
||||
| `DATABASE_PATH` | No | `./dyn.db` | SQLite database path |
|
||||
| `SERVER_PORT` | No | `8080` | HTTP server port |
|
||||
| `RATE_LIMIT_PER_IP` | No | `10` | Requests per minute per IP |
|
||||
| `RATE_LIMIT_PER_TOKEN` | No | `1` | Updates per minute per token |
|
||||
| `TRUSTED_PROXIES` | No | - | Comma-separated CIDRs |
|
||||
|
||||
*Either `TECHNITIUM_TOKEN` OR both `TECHNITIUM_USERNAME` and `TECHNITIUM_PASSWORD` required.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Local development
|
||||
go mod tidy
|
||||
go run cmd/server/main.go
|
||||
|
||||
# Build
|
||||
go build -o server cmd/server/main.go
|
||||
|
||||
# Test
|
||||
go test ./...
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Credits
|
||||
|
||||
Inspired by [benjaminbear/docker-ddns-server](https://github.com/benjaminbear/docker-ddns-server)
|
||||
Reference in New Issue
Block a user