Skip to content

ODickins/DTooling

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DTooling.DnsServer

A lightweight, embeddable DNS server implementation in C# built on top of UDP sockets.
The server listens on port 53 and resolves DNS queries via event-based lookup handlers that you plug in at runtime.

This design makes it easy to embed a DNS server inside another application and dynamically control how records are resolved.


✨ Features

  • UDP-based DNS server (RFC-style packet handling)
  • Supports multiple DNS record types:
    • A, AAAA
    • NS
    • CNAME
    • SOA
    • PTR
    • MX
    • TXT
    • ANY
  • Event-driven lookup pipeline
  • Async / non-blocking request handling
  • Minimal dependencies
  • Optional Microsoft.Extensions.Logging support

📦 Installation

Add the project reference or NuGet package (if published):

dotnet add package DTooling.DnsServer

Or reference the project directly:

<ProjectReference Include="DTooling.DnsServer.csproj" />

🚀 Basic Usage

1. Create the DNS server instance

using DTooling.DnsServer;

var dnsServer = new DnsServerInstance();

Or with logging:

using Microsoft.Extensions.Logging;

var logger = loggerFactory.CreateLogger<DnsServerInstance>();
var dnsServer = new DnsServerInstance(logger);

2. Register lookup handlers

Each DNS record type is resolved via an event handler. You can register one or more handlers per record type.

Example: handling A records

dnsServer.LookupARecordAsync += async (endpoint, question, ct) =>
{
    if (question.Name == "example.com")
    {
        return DnsLookupResult.Success(
            DnsAnswer.A(question.Name, IPAddress.Parse("127.0.0.1"))
        );
    }

    return DnsLookupResult.Failure();
};

Handlers are executed in order. The first handler that returns a successful result wins.


3. Start the server

// Default: 0.0.0.0:53
dnsServer.Start();

// Or bind to a specific port
dnsServer.Start(new IPEndPoint(IPAddress.Loopback, 5353));

The server will now:

  • Bind to 0.0.0.0:53

  • Accept UDP DNS queries

  • Respond with:

    • NOERROR when a record is resolved
    • NXDOMAIN when no handler succeeds
    • SERVFAIL on internal errors

⚠️ Binding to port 53 may require administrator/root privileges.


4. Stop the server

await dnsServer.StopAsync();

Or dispose it:

dnsServer.Dispose();

🧠 How Resolution Works

  1. DNS packet is received over UDP
  2. Packet is parsed into a DnsMessage
  3. Each question is processed independently
  4. Based on DnsType, the corresponding event is invoked
  5. Handlers return a DnsLookupResult
  6. Successful results are added as answers
  7. Response is serialized and sent back to the client

🔌 Supported Lookup Events

LookupARecordAsync
LookupAaaaRecordAsync
LookupNsRecordAsync
LookupCnameRecordAsync
LookupSoaRecordAsync
LookupPtrRecordAsync
LookupMxRecordAsync
LookupTxtRecordAsync
LookupAnyRecordAsync

Each event signature:

Func<IPEndPoint, DnsQuestion, CancellationToken, ValueTask<DnsLookupResult>>

🧪 Testing the Server

Use standard DNS tools:

dig @127.0.0.1 example.com A
nslookup example.com 127.0.0.1

⚠️ Notes & Limitations

  • UDP only (no TCP fallback)
  • No zone file parsing (by design)
  • No caching layer
  • Designed for embedded / programmable DNS, not full authoritative servers

📜 License

Licensed under the Apache License 2.0. See the LICENSE file for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages