
Show HN: MassDNS – A high-performance DNS stub resolver in C - blechschmidt
https://github.com/blechschmidt/massdns
======
audidude
// SECURITY IMPROVEMENTS REQUIRED. VULNERABLE TO INTEGER AND BUFFER OVERFLOWS.

well at least it's pretty clear up front. No malloc result checks, invalid
format in printfs, probably more.

(I don't mean to be disparaging, please don't take it that way OP. We clearly
need more/better tooling in this area in C).

(Edited for clarity)

~~~
tptacek
Malloc result checks are generally a bad idea; they're error prone. Better
just to run with the allocator configured to abort on failure.

~~~
audidude
Generally agree, (and that's what we usually do in GLib). However, for a
general purpose DNS user-space implementation I think it would be good to have
something that can be used in both scenarios.

~~~
tptacek
That's a coherent argument, but that argument is also, I think, probably
responsible for virtually all of the exploitable offset-from-NULL
vulnerabilities shipped in C code.

------
blumentopf
Ugh, so public resolvers are flooded with requests? Wouldn't it make much more
sense to set up a local _caching_ resolver like unbound and feed your queries
to it? It would be much more considerate towards the public resolvers and also
use less of your own bandwidth.

~~~
matt_wulfeck
There are valid use cases for this. For example, web crawling needs to do
millions of resolutions _one time_ which completely nullifies the need for a
cache.

~~~
blumentopf
For this to be correct, all records to be resolved would need to have
completely disjunct labels from the root down. Which they cannot if they are
indeed in the millions.

~~~
blechschmidt
I have not yet managed to setup a single local recursor, such as PowerDNS
recursor, to deliver the same performance as the list consisting of multiple
open resolvers, although bandwidth does not seem to be the limiting factor.
Testing with dnsperf, the best result I am currently getting is about 6,000
resolves per second with bind, for PDNS the figure is even lower for some
reason. I will have to dig a bit deeper in order to find the reason for that
cap.

~~~
blumentopf
I'm not surprised at all that BIND performs poorly, look at those graphs
(granted this is for authoritative servers, but says a lot about BIND's
performance in general):
[https://www.nlnetlabs.nl/blog/2013/07/05/nsd4-performance-
me...](https://www.nlnetlabs.nl/blog/2013/07/05/nsd4-performance-
measurements/)

I'd stick with Unbound. There are a lot of knobs to fiddle with in the config.
Be sure to compile against libevent so that you can use the highly scalable
epoll as a backend (assuming you're on Linux). Turn up all the limits for
cache size etc. Disable DNSSEC validation if you don't care about spoofed
records. Ask on the mailing list if you need help, Wouter and his colleagues
are very nice and respond very quickly.

------
textmode
"A high-performance non-recursive DNS resolver"

I believe a better description for this program would be a "stub resolver".

~~~
blechschmidt
This is already discussed below and you are right. It was an issue with the
perspective of the term recursion from my side. Unfortunately, I cannot change
the HN title anymore. (Maybe some moderator can?) The GitHub project
description has been changed.

Some of the resolvers might ban/rate-limit you indeed and even send abuse
complaints to your ISP.

EDIT: You might have a look at the newly implemented --norecurse option.

~~~
textmode
"\--norecurse Useful for DNS cache snooping"

Not if the resolver rejects non-recursive queries, as do dnscache and dqcache.

There is a way to resolve DNS domainnames to IP addresses using only non-
recursive queries. I do it everyday.

But I've never seen anyone release any program that did this. Your program
does not even attempt to do this -- you need to send the queries to
authoritative nameservers not public resolvers. But you used the term "non-
recursive" so I thought maybe someone had finally tried.

One of the shortcomings of DNS IMO is that the specification allows for the
possibility of including more than one name in a query. But no one has ever
implemented this, as far as I know.

Despite the design of the DNS, most of the information stored in it is more
static than dynamic, and much of it is centralized. Most dommainnames do not
change IP addresses very often and there are very large numbers of domainnames
sharing the same authoritative nameservers.

~~~
blechschmidt
For DNS cache snooping the usage would of course be different. You would
supply the tool with one resolver which does not reject non-recursive queries.
Theoretically, one could even perform traffic analyses of DNS resolvers by
snooping.

Having implemented the --norecurse option, the title is at least not wrong
anymore. One can have non-recursive, non-iterative resolver (which is what you
use when you want to perform DNS cache snooping) and the title does not
suggest that the tool supports iterative lookups.

Handling multiple questions within one packet is difficult because response
codes such as NXDOMAIN are only included once per packet. AFAIK, bind does not
support handling such queries.

~~~
textmode
"AKAIK, bind does not support handling such queries."

AKAIK, there is not a server in existence that handles such queries.

Cache snooping is not very reliable. I tested the 999 open resolvers listed in
resolvers.txt for example.com and only 643 of them returned an answer. 13 of
those answers were fake.

Moreover, there are at least hundreds of thousands of domainnames that will
not be in any given cache.

Finally, most internet users are probably not using open resolvers. They are
more likely using the ones provided by their ISP, which are not open.

Anyway, I doubt anyone is ever going to release a non-recursive resolver.

I have my own solution which is too embarrasing to release but I can tell you
it is usually faster than a recursive resolver if the cache is not already
primed with the right records.

To me, "non-recursive" resolution means something specific -- no use of DNS
caches. And because of that there's no risk of "cache poisoning".

------
dmlittle
What are the benefits of resolving DNS entries in a non-recrusive manner? A
recursive resolve means that the final resolution of the domain is cached by
the original DNS server that was queried along with all the servers it took to
resolve. My understanding is that this behavior was ideal.

~~~
blechschmidt
What I mean by non-recursive in this case is that the program does not perform
recursion by itself as it relies on a list of DNS resolvers. When querying
these resolvers, the recursion bit is actually set. However, I agree that the
title might be misleading but I am not sure how I could express that better.

~~~
nickpsecurity
Yeah, most titles I just brainstormed still suck in some way. Yours is
technically true but only locally. Perhaps add something like you just said to
the opening paragraph. That reduces confusion on what non-recursive means
along with saving reader any wasted time if they were seeking something else.

~~~
blechschmidt
Well, in order to make it correct, I have implemented a --norecurse option.

------
jedisct1

        if (packet->flags & DNS_RESPONSE_FLAG == 0 || packet->questioncount != 1)
    

I'm not sure that it does what you want.

~~~
blechschmidt
This is the line of code that pre-checks whether an incoming packet should be
parsed at all. If it is not a response packet or if the number of questions is
not one, it should not be parsed, simply because the packet parsing function
expects a reply packet with exactly one question, namely the one that has been
queried for.

~~~
abhorrence
Operator precedence causes it to be interpreted as:

    
    
      if ((packet->flags & (DNS_RESPONSE_FLAG == 0)) || (packet->questioncount != 1))
    

which at least does not read as intended.

~~~
blechschmidt
You are correct. Has been fixed.

------
known
You may want to test it with [http://www.verisign.com/en_US/channel-
resources/domain-regis...](http://www.verisign.com/en_US/channel-
resources/domain-registry-products/zone-file/index.xhtml)

------
otterley
For easy comparability, request handling rates of tools like this are best
described in terms of requests per second, not requests per hour. Also the
hardware on which the benchmarks were performed needs to be described in
detail.

Are you sure tinydns, which has existed for ages without security
vulnerabilities, can't trivially handle 27k requests/second on modern
hardware?

~~~
blechschmidt
I have not heard about tindydns before but it seems to be a DNS server, not a
client.

The tool has mainly been tested on a Hetzner EX41 server. (Ubuntu, Intel®
Core™ i7-6700, 32 GB RAM)

~~~
otterley
Ah, you are correct. There is also dnscache, which is part of the same suite.
However, it does not do what you are attempting to do.

