Deprecated! Moved to: spaaleks/technitium-api-proxy
2.1K
A security proxy for Technitium DNS Server that adds fine-grained access control to the Technitium HTTP API. It runs as a standalone FastAPI service, forwarding allowed requests to the upstream Technitium server while enforcing token-based policies.
Clients use the standard Technitium API. They just point at the proxy instead of Technitium directly.
config.yml) with per-token access policiesget, add, update, delete)A, AAAA, CNAME, TXT, etc.)/api/zones/list responses only show zones the token is allowed to accessThe proxy sits between clients and the Technitium DNS Server:
Client --> Proxy (port 31399) --> Technitium (port 5380)
X-API-Token header or ?token= query param)| Tier | Endpoints | Access |
|---|---|---|
| Tier 1 | /api/zones/records/*, /api/zones/list | Allowed (with policy checks) |
| Tier 2 | /api/zones/create, /api/zones/delete, /api/zones/enable, /api/zones/disable, /api/zones/import, /api/zones/export | Blocked |
| Tier 3 | All other /api/* (admin, settings, etc.) | Blocked |
services:
technitium-api-proxy:
image: spaleks/technitium-api-proxy:latest
# or quay.io/spaleks/technitium-api-proxy:latest
ports:
- "31399:31399"
volumes:
- ./config.yml:/app/config.yml:ro
docker run --rm \
-p 31399:31399 \
-v "$(pwd)/config.yml:/app/config.yml:ro" \
spaleks/technitium-api-proxy:latest
config.yml)technitium:
url: "http://localhost:5380"
token: "your-admin-api-token"
verify_ssl: true
tokens:
# Full access to a zone
- name: "full-access"
token: "client-secret-token"
zones:
- name: "example.com"
allowed_record_types: ["A", "AAAA", "CNAME", "TXT"]
allowed_operations: ["list", "get", "add", "update", "delete"]
# Only manage records under app.example.com
# Allows: app.example.com, api.app.example.com, v2.app.example.com
# Denies: www.example.com, mail.example.com
- name: "app-team"
token: "app-team-secret"
zones:
- name: "example.com"
subdomain_filter: "app."
allowed_record_types: ["A", "AAAA", "CNAME"]
allowed_operations: ["list", "get", "add", "update", "delete"]
# Read-only access to all zones (no zone scoping)
- name: "monitoring"
token: "monitoring-secret"
global_read_only: true
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Display name for audit logs |
token | string | required | The secret token clients use to authenticate |
global_read_only | bool | false | Allow read-only access to all zones (ignores zones) |
zones | list | [] | Zone-level access policies |
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | DNS zone name (e.g. example.com) |
allowed_record_types | list | [] (all) | Restrict to specific record types (A, AAAA, CNAME, TXT, MX, etc.) |
allowed_operations | list | [] (all) | Restrict to specific operations (get, add, update, delete) |
subdomain_filter | string | null | Only allow records whose domain starts with this prefix |
Empty lists mean "all allowed". Omit allowed_record_types to allow all record types, omit allowed_operations to allow all operations.
Download the binary from the releases page:
chmod +x technitium-api-proxy
CONFIG_PATH=./config.yml ./technitium-api-proxy
git clone https://github.com/spaaleks/technitium-api-proxy.git
cd technitium-api-proxy
bin/start.sh
| Variable | Default | Description |
|---|---|---|
CONFIG_PATH | config.yml | Path to the YAML configuration file |
HOST | 0.0.0.0 | Host/IP to bind |
PORT | 31399 | Port to bind |
LOG_LEVEL | info | Log level (debug, info, warning, error) |
Clients authenticate by passing their token in one of two ways:
Header (preferred):
curl -H "X-API-Token: your-token" http://proxy:31399/api/zones/list
Query parameter:
curl http://proxy:31399/api/zones/list?token=your-token
The header takes precedence if both are provided.
Inspired by powerdns-api-proxy and the Technitium feature request TechnitiumSoftware/DnsServer#958.
MIT
Content type
Image
Digest
sha256:d154554a4…
Size
50.1 MB
Last updated
6 months ago
docker pull spaleks/technitium-api-proxy