Getting started

edit

Install the packages

Add the packages to a project:

dotnet package add Meziantou.Framework.DnsClient
dotnet package add Meziantou.Framework.DnsServer
dotnet package add Meziantou.Framework.DnsFilter

To run the DNS proxy instead, install the tool. See Running the proxy.

Query a DNS server

Create a DnsClient with the address of the server and the transport, then call QueryAsync with a name and a record type. serverAddress is the address of the server, such as "192.0.2.53" or "127.0.0.1:5053":

using var client = new DnsClient(serverAddress, DnsClientProtocol.Udp);
var response = await client.QueryAsync("www.example.com", DnsQueryType.A);

Assert.Equal(DnsResponseCode.NoError, response.Header.ResponseCode);
var addresses = response.Answers.OfType<DnsARecord>().Select(record => record.Address).ToList();
Assert.Equal([IPAddress.Parse("192.0.2.10")], addresses);

Answer DNS queries

The server runs in an ASP.NET Core application. AddDnsServer adds the listeners, and MapDnsHandler registers the callback that answers every query. Here, port is the port to listen on (53 is the standard one):

var builder = WebApplication.CreateBuilder();
builder.AddDnsServer(options =>
{
    options.AddUdpListener(port, IPAddress.Loopback);
    options.AddTcpListener(port, IPAddress.Loopback);
});

var app = builder.Build();
app.MapDnsHandler((context, cancellationToken) =>
{
    var response = context.CreateResponse();
    foreach (var question in context.Query.Questions)
    {
        if (question.Type is DnsQueryType.A && string.Equals(question.Name, "www.example.com", StringComparison.OrdinalIgnoreCase))
        {
            response.Answers.Add(new DnsResourceRecord
            {
                Name = question.Name,
                Type = DnsQueryType.A,
                Class = DnsQueryClass.IN,
                TimeToLive = 300,
                Data = new DnsARecordData { Address = IPAddress.Parse("192.0.2.10") },
            });
        }
    }

    return ValueTask.FromResult(response);
});

Use the client and the server in the same file

Both packages define types with the same names (DnsQueryType, DnsQueryClass, DnsResponseCode, DnsQuestion, DnsEdnsOptions, DnsProtocolException), in different namespaces. A file that imports both sets of namespaces gets ambiguous references: import one of them, and refer to the other through an alias, such as using ServerProtocol = Meziantou.Framework.DnsServer.Protocol;.

Next steps

  • DnsClient: transports, record types, DNSSEC, errors.
  • DnsServer: listeners, handlers, serving a zone.
  • DnsFilter: block lists and filtering rules.