This document describes the high-level architecture, component design, and data flows of the LLM over DNS server.
LLM over DNS is an asynchronous, stateless UDP DNS server written in Rust. It functions as a gateway that intercepts incoming standard DNS TXT record queries, forwards the prompt to an LLM provider (AnyRouter or OpenRouter), chunks the response, and returns standard DNS records to the client.
graph TD
Client["DNS Client (e.g., dig, nslookup)"] -->|1. TXT UDP Query| Server["LLM over DNS Server (Rust + Tokio)"]
Server -->|2. Validate & Parse| Handler["DnsHandler"]
Handler -->|3. Forward Prompt| ClientAPI["LlmClient"]
ClientAPI -->|4. HTTP JSON Request| Gateway["LLM Gateway (AnyRouter / OpenRouter)"]
Gateway -->|5. Forward Inference| LLM["LLM (Gemini, Llama)"]
LLM -->|6. Answer Text| Gateway
Gateway -->|7. HTTP Response| ClientAPI
ClientAPI -->|8. Clean String| Handler
Handler -->|9. Split 255-char Chunks| Chunker["Chunker"]
Chunker -->|10. Build TXT records| Handler
Handler -->|11. Send DNS Packet| Client
The codebase is modularized into isolated components designed for testability and thread-safe parallel processing:
main.rs & server.rs)hickory-server and hickory-proto (version 0.26) for parsing raw wire packets into structured Message objects.dns_handler.rs)llm_client.rs)https://anyrouter.dev/api/v1/chat/completions with optimized model routing.https://openrouter.ai/api/v1/chat/completions.chunker.rs)Let’s trace a typical request:
5454. The server spawns a new async Tokio task to process it.DnsHandler extracts the query name. E.g. what-is-rust.example.com is parsed into the query prompt "what is rust".LlmClient makes a POST request to AnyRouter.429 or 502), the client instantly triggers a backup model query.Chunker.Message with the array of chunked TXT records and sends it back to the client.FORMERR status codes..env.local files) and are masked in startup logs to prevent accidental exposure.reqwest ensures low overhead per query.< 1 second.5-50ms (overhead).0.8 - 4 seconds (inherent upstream latency).1.5 - 5 seconds.~10MB baseline, scaling to ~50MB under heavy load.assert_matches assertions).tests/integration_test.rs) simulating actual UDP server/client sockets.