murarth/resolve

Support for NS records

Closed this issue · 12 comments

dbrgn commented

Support for resolving NS records would be great.

In addition to raw record resolving, how easy would it be to provide a function to find the authoritative name servers for a domain?

dbrgn commented

(Reason for this request: I'm currently querying TXT records through default_config(), but that potentially results in caching problems. So I'd like to create a resolver that uses the authoritative nameservers directly.)

Added support for NS records in 52acca7.

In addition to raw record resolving, how easy would it be to provide a function to find the authoritative name servers for a domain?

I'm not sure what you're asking for here. DnsResolver::resolve_record::<Ns> would give you the list of NS records for a given host.

dbrgn commented

Wow, you're fast! :) Thanks a lot for your work.

I'm not sure what you're asking for here. DnsResolver::resolve_record:: would give you the list of NS records for a given host.

If I have a subdomain (e.g. sub.example.com) that only has a TXT record associated:

$ dig +short TXT mg.dbrgn.ch
"v=spf1 include:mailgun.org ~all"

If I query this subdomain for NS records, it doesn't have any (but there could be some):

$ dig +short NS mg.dbrgn.ch
$

If I'm not mistaken, the correct thing to do would be to strip the first segment from the domain and try again. Or is that wrong?

Also, when I leave away the "+short" option, then the dig tool does show an AUTHORITY SECTION. Is that contained in every response? Or is that cached somehow, or queried each time?

If I'm not mistaken, the correct thing to do would be to strip the first segment from the domain and try again. Or is that wrong?

I don't think there's necessarily a notion of objective "correctness" with respect to this problem, but my DNS knowledge is admittedly limited, so I may be wrong. If you can find a reference for this kind of operation performed by something that's widely found in the wild (e.g. in some popular software), then I'll consider implementing this. Otherwise, I think it would be pretty easy to perform this operation on top of the existing API.

Edit: A reference to an RFC would also suffice, of course.

dbrgn commented

Hm, it looks like the authoritative nameservers are included in all NS responses, they're just ignored when using dig +short if they're not set directly on the subdomain.

I got a problem using the NS resolution though. When trying to resolve mg.dbrgn.ch I get an InvalidName error. The problem is here:

 182                 // To prevent an infinite loop, we require the pointer to                           
 183                 // point before the start of this name.                                             
 184                 if offset >= start_pos {                                                            
 185                     return Err(DecodeError::InvalidName);                                           

I inserted some print statements into the code, it ended with the following output:

Len: 192 (11000000)
Offset: 12
Start pos: 176
Len: 5 (101)
Len: 2 (10)
Res: dbrgn.ch.
------
Len: 192 (11000000)
Offset: 101
Start pos: 190
Len: 18 (10010)
Len: 11 (1011)
Len: 192 (11000000)
Offset: 50
Start pos: 190
Len: 3 (11)
Res: v22011081724612999.yourvserver.net.
------
Len: 192 (11000000)
Offset: 101
Start pos: 206
Len: 18 (10010)
Len: 11 (1011)
Len: 192 (11000000)
Offset: 50
Start pos: 206
Len: 3 (11)
Res: v22011081724612999.yourvserver.net.
------
Len: 2 (10)
Len: 8 (1000)
Len: 3 (11)
Res: de.ch-inter.net.
------
Len: 2 (10)
Len: 192 (11000000)
Offset: 41
Start pos: 0
failed to resolve record: error decoding message: invalid name

So for some reason the offset is 41 while the start pos is 0.

In Wireshark it looks like this:

img

I think the error occured in the "Additional records" section.

dbrgn commented

I tried to debug some more (I understand now how the references work), but could not find the exact reason why start_pos is zero...

I think I know what the problem is: The content of a resource record is parsed in isolation, not as part of the whole message. Therefore, if a resource record's data contains a name and that name is expressed using a pointer reference, the parser will get confused by the offset. I'm developing a fix now.

Fixed: 0795053

dbrgn commented

Great, thanks! I already thought it had to do with that.

Only gripe now:

$ cargo run --example lookup_ns dbrgn.ch
     Running `target/debug/examples/lookup_ns dbrgn.ch`
NS name=ch.ch-inter.net.
NS name=nl.ch-inter.net.
NS name=v22011081724612999.yourvserver.net.
NS name=de.ch-inter.net.
NS name=nl.ch-inter.net.
NS name=v22011081724612999.yourvserver.net.
NS name=de.ch-inter.net.
NS name=ch.ch-inter.net.

The returned values are a combination of authority records and answer resource records.

I'm not sure whether a regular NS query should return the entries of the authority section at all. Strictly speaking they're not NS records. I could still use them in my case tough.

Do we need separate handing for the two parts?

Yes, this does seem wrong. It's the result of me not having understood DNS very well as I began implementing this. I'm pushing a fix now; resolver requests will check only records in the answer section. If an application wants to look at other sections, it will need to use DnsResolver::send_message to view the entire message.

dbrgn commented

Sounds good!

dbrgn commented

I think we can close this now :)