Introduction

One of the things I needed to complete my self-written spam-stopper, which acts like an SMTP proxy, is resolving DNS queries, reading SPF1 records, doing reversed lookups, etc. On the .NET (2.0) framework, there is a simple implementation of a DNS component. But it is far from complete. The other project on DNS resolving on CodeProject, C# .NET DNS query component, by Rob Philpott is old, buggy, incomplete, and not supported anymore. It was time to take the official RFCs on DNS and build the application from ground up. I must admit, the influence of Rob's project is there, but the code is definitely not the same.

Background

As mentioned before, the basics of DNS is explained in RFCs. (Request For Comments). These are the RFCs I used for the initial project:

Using the Code

The main core of DNS resolving is the 'resolver'. This class wraps queries into DNS packets and sends them to any DNS server. The response is then decoded into some useful information (at least for programmers, or for me in special ). All my DNS stuff uses the namespace Heijden.DNS. Don't change it in your applications, it gives me some comfort knowing my name is stored in some nice other projects. Don't forget to let me know.

Because I don't want to go immediately into details in this article, I only show the usage of the resolver component to warm you up. As the best way to do this, I have built a Dig class which acts like the good-old-Unix-style dig. Its acts like dig, but it is not a complete dig implementation. It does, however, do everything you want it to, presenting the output in more or less the same format.

The resolver uses the default DNS servers which are used on your Windows machine. A good alternative is to use Resolve.DefaultDnsServers which are the two servers from www.opendns.com and are free to use. The resolver accepts any DNS server, or servers. You can add as many as you need, specifying any IP and/or port number.

The main method to do queries to DNS servers is Query. In the dig example, I used a stopwatch to measure the total roundtrip time.

Give Me More Details

Okay, Dig is good. But, the workhorse is the Resolver class. It has got so many secrets. I will try to reveal all of them.

The resolver uses two main classes to do its work. It uses a Query class and delivers a Response class. Querying a DNS server can be done by the TCP or UDP transport protocols. The main DNS methods can be used synchronously and asynchronously. This took me really much typing work. Some headaches and no sleep to do it right. All responses can be stored in a real-time response cache. It uses the Time-To-Live properties of the response records which can be viewed in the Dig application by doing the same queries over and over again (it counts down the TTL values). The caching of records speeds up applications tremendously.

Public constants, constructors, properties, and methods which can be used on the resolver:

That's about it. The classes in the project are more or less well documented. So, programming must not be so difficult.

Points of Interest

Nowadays, networks have started using the IPv6 range more and more. In this project, IPv6 is 100% supported. An example of this is when doing lookups for the AAAA record or PTR lookups, like this one (PTR on 2001:0610:0000:800a:b192:0087 .5.0.152):

In the Dig example, the translation of the phone-number is done automatically when using NAPTR lookups (can be switched off by the checkbox). The example ANSWER output is edited to protect some data, shown as .... ---- and ++++ , but it works in real-life

History

As of writing, the version of this project is 1.0.0.0:

April 4, 2008: Thanks to Martin G C Davies for fixing the GetDNSServers routine to take only the 'OperationalStatus.Up' interfaces.

April 4, 2008: Thanks to 'gbonnet' for pointing me to the 'NAPTR' records, it is added to the project.

May 20, 2008: Jon Webster has fixed the duplicate entries in DNS servers.

July 18, 2008: Added some handy code to do NAPTR lookups.

Version: 1.0.0.1

May 20, 2008: The source code / demo code is much newer than this article. Almost any possible DNS record is added to the project. But implementation is not complete. Anyone is invited to implement the 'empty' DNS record types.

Share

About the Author

I'm Alphons van der Heijden, living in Lelystad, Netherlands, Europa, Earth. And currently I'm retiring from hard working ( ;- ), owning my own company. Because I'm full of energy, and a little to young to relax ...., I don't sit down, but create and recreate software solutions, that I like. Reinventing the wheel is my second nature. My interest is in the area of Internet technologies, .NET etc. I was there in 1992 when Mosaic came out, and from that point, my life changed dramatically, and so did the world, in fact. (Y)

So by your logic, if a CodeProject member submits a low vote for an article they then have to submit code to amend its obvious deficiencies in order for their vote to be deemed worth full? I don’t think that’s reasonable.

I'd be interested in hearing reading more about the DNS response validation you are talking about. Is this something that can be found online, or is it something you learned on your own? If so, can you share some guidance here?

The points I mentioned are detailed in RFC5452: Measures for Making DNS More Resilient against Forged Answers. It specifies that, as a minimum, resolvers should match the question section, query ID and, for UDP queries, match the source address of the response.