Skip to content

Architecture

ovx-labs edited this page Sep 5, 2026 · 2 revisions

Architecture

DNS Chain Overview

                           +------------------+
                           |  Client Query    |
                           +--------+---------+
                                    |
                                    v
                           +------------------+
                           |  Pi-hole (53)    |  -- blocking, cache
                           |  forwarder       |
                           +--------+---------+
                                    |
                                    v
                           +------------------+
                           |  CoreDNS (5352)  |  -- split-horizon, local zones
                           +--------+---------+
                                    |
                                    v
                           +------------------+
                           |  dnsdist (5330)  |  -- load balance, retry, Lua policy
                           +--------+---------+
                    +--------+--------+--------+
                    |                 |        |
                    v                 v        v
             +------------+    +------------+  +------------+
             | Unbound    |    | Stubby     |  | DNSCrypt   |
             | (5335)     |    | (5360)     |  | (5354)     |
             | recursive  |    | DoT proxy  |  | DoH proxy  |
             +-----+------+    +-----+------+  +-----+------+
                   |                 |                |
                   +--------+--------+----------------+
                            |
                            v
                   +------------------+
                   |  VPN DNS         |  -- discovered dynamically
                   |  (Proton/Nord/   |
                   |   Tailscale)     |
                   +------------------+

                           +------------------+
                           |  agentic-dns-    |  -- Rust DoT/mTLS proxy
                           |  server (853)    |     on 127.0.0.1 or Tailscale
                           +------------------+

Data Flow

  1. Client query hits Pi-hole (port 53)
  2. Pi-hole blocks/forwards to CoreDNS
  3. CoreDNS applies split-horizon, forwards to dnsdist
  4. dnsdist load-balances across Unbound/Stubby/DNSCrypt
  5. Resolvers query VPN DNS or public DoH
  6. Response flows back through chain
  7. agentic-dns-server (Rust) terminates DoT on 853, forwards to Pi-hole

Event-Driven Reconciliation

Similar to agentic-route:

  • inotifywait watches /etc/agentic-dns/ configs
  • agentic-dns CLI discovers services, health-checks
  • VPN DNS changes trigger dnsdist/CoreDNS reconfig
  • State emitted to logs/REST API/MCP

Adding New Resolvers/Tools (Trivial)

The entire chain is designed for drop-in extensibility — adding a new upstream resolver takes one command and zero code changes.

Via CLI (Instant)

# Add any DNS server as dnsdist upstream
agentic-dns route add myresolver 1.2.3.4:53

# Add DoT upstream
agentic-dns route add dot-resolver 1.1.1.1:853

# Add DoH upstream (via dnscrypt-proxy stamp)
agentic-dns route add doh-resolver https://dns.example.com/dns-query

# List current upstreams
agentic-dns routes

Via REST API

curl -X POST http://localhost:8099/api/v1/route   -H "Content-Type: application/json"   -d '{"name": "myresolver", "addr": "1.2.3.4:53"}'

Via MCP

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"dns_route_add","arguments":{"name":"myresolver","addr":"1.2.3.4:53"}}}

What Happens Automatically

Step Action
1 dnsdist config updated with new server line
2 dnsdist reloaded (zero-downtime, dnsdist -C)
3 Health check runs against new upstream
4 Added to /api/v1/status and MCP dns_status
5 Load-balanced immediately with existing upstreams

Supported Resolver Types

Type Port Config Location Example
Plain UDP/TCP 53 dnsdist 1.1.1.1:53
DoT (TLS) 853 dnsdist + Stubby 9.9.9.9:853
DoH (HTTPS) 443 dnscrypt-proxy stamp https://dns.quad9.net/dns-query
DoQ (QUIC) 784 Not yet
Local recursive 5335 Unbound config 127.0.0.1:5335

Adding a Full New Service (e.g., Knot, PowerDNS, AdGuard)

  1. Install the service (systemd unit)
  2. Add one line to SERVICES array in bin/agentic-dns:
    "knot|53|127.0.0.1|authoritative|none"
  3. Run agentic-dns health — it auto-detects and includes it

No daemon restart, no config templates, no code changes. The tooling discovers what's listening and integrates it.

Clone this wiki locally