Skip to content

Instantly share code, notes, and snippets.

@shaltielshmid
Created August 6, 2025 15:17
Show Gist options
  • Select an option

  • Save shaltielshmid/6a9e2a67b6c28e0ce5cf1917326e5aa6 to your computer and use it in GitHub Desktop.

Select an option

Save shaltielshmid/6a9e2a67b6c28e0ce5cf1917326e5aa6 to your computer and use it in GitHub Desktop.
Reproduction of LLM-over-DNS in C# 10
#:package ARSoft.Tools.Net@3.6.1
#:package LLMTornado@3.7.25
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;
using LlmTornado.Code;
using LlmTornado;
using LlmTornado.Chat;
(string EnvKey, LLmProviders Provider)[] Providers = [
("GOOGLE_API_KEY", LLmProviders.Google),
("OAI_API_KEY", LLmProviders.OpenAi),
("ANTHROPIC_API_KEY", LLmProviders.Anthropic),
("OPENROUTER_API_KEY", LLmProviders.OpenRouter),
("COHERE_API_KEY", LLmProviders.Cohere),
("GROQ_API_KEY", LLmProviders.Groq),
("DEEPSEEK_API_KEY", LLmProviders.DeepSeek),
("MISTRAL_API_KEY", LLmProviders.Mistral),
("XAI_API_KEY", LLmProviders.XAi),
("PERPLEXITY_API_KEY", LLmProviders.Perplexity)
];
// Get the model
string? model = Environment.GetEnvironmentVariable("LLM_MODEL");
if (string.IsNullOrWhiteSpace(model))
throw new ArgumentException("LLM_MODEL configuration is required.");
// Get the configured provider (Will throw error if not found)
var provider = Providers.First(p => !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(p.EnvKey)));
var api = new TornadoApi(Environment.GetEnvironmentVariable(provider.EnvKey)!, provider.Provider);
var server = new DnsServer();
server.QueryReceived += async (object sender, QueryReceivedEventArgs e) => {
try {
var query = e.Query as DnsMessage ?? throw new ArgumentException("Query is not a valid DNS message.");
if (query.Questions.Count != 1 || query.Questions[0].RecordType != RecordType.Txt)
return;
var response = query.CreateResponseInstance();
e.Response = response;
var domain = query.Questions[0].Name;
var llmResult = await api.Chat.CreateConversation(model)
.AppendAssistantMessage("You are a helpful assistant who responds very very concisely.")
.AppendUserInput(domain.ToString())
.GetResponseRich();
// Break it up into chunks of 250 chars (TODO: handle bytes)
int offset = 0;
while (offset < llmResult.Text.Length) {
response.AnswerRecords.Add(new TxtRecord(domain, 3600, llmResult.Text[offset..Math.Min(llmResult.Text.Length, offset + 250)]));
offset += 250;
}
response.ReturnCode = ReturnCode.NoError;
}
catch (Exception ex) {
Console.WriteLine("Error processing DNS query: " + ex.Message);
}
};
server.Start();
Console.WriteLine("DNS server started on port 53");
try {
await Task.Delay(Timeout.Infinite, CancellationToken.None);
}
finally {
server.Stop();
Console.WriteLine("DNS server stopped");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment