Skip to content

Conversation

@BobSilent
Copy link

@BobSilent BobSilent commented Oct 25, 2022

Fixes #23

Try next nameserver if current nameserver response is RCode::ServFail

@BobSilent
Copy link
Author

@hsbt how can we get this merged?

@hsbt
Copy link
Member

hsbt commented Nov 7, 2023

Can you add test for this at least?

@BobSilent
Copy link
Author

Sure i will do so (or at least will give it a try - I am not a ruby pro 😉)

@BobSilent BobSilent force-pushed the handle-nameserver-servfail-reply branch from 048a670 to b66db3b Compare November 15, 2023 20:05
@BobSilent BobSilent force-pushed the handle-nameserver-servfail-reply branch from b66db3b to f53cea1 Compare November 15, 2023 20:08
@BobSilent
Copy link
Author

@hsbt please have a look at the added test case.

@BobSilent
Copy link
Author

@hsbt did you had a chance to look into this?

@BobSilent
Copy link
Author

@hanazuki, @hsbt anything else I can add/update here?

@hanazuki
Copy link
Contributor

I have examined the logic but don't know if this works with TCP fallback.

I'm thinking of a situation as follows:

  • The Resolv::DNS instance is configured with two nameservers NS1 and NS2 in this order.
  • NS1's TCP listener is somehow broken and returns ServFail.
  • The requested resource records are large and don't fit in a UDP response.

In this case, it is expected that:

  1. Resolv first queries NS1 with UDP. NS1 will respond with NoError with TC=1.
  2. Resolv then falls back to TCP and queries NS1 with TCP. NS1 will respond with ServFail.
  3. Resolv tries the next nameserver with TCP. NS2 will respond with NoError. This answer is returned to the caller.

IIUC, the proposed implementation will:

  1. changes the variable requester to make_tcp_requester(nameserver, port) when it receives a UDP message with TC=1 (so this host/port pair is NS1's),
  2. queries the same server (NS1) and gets a ServFail, and then
  3. uses the same requester to query NS2, which results in an error due to the unmatched host/port pair.

To make this work properly, maybe we have to reset the requester before next.

  when RCode::ServFail
    if Requester::TCP === requester
      requester.close
      requester = nil  # next iteration assigns new TCP requester
    end
    next

Sorry if I'm wrong. I feel confused 😵 .

@hanazuki
Copy link
Contributor

hanazuki commented Dec 14, 2023

To make this work properly, maybe we have to reset the requester before next.

  when RCode::ServFail
    if Requester::TCP === requester
      requester.close
      requester = nil  # next iteration assigns new TCP requester
    end
    next

I found this was not a sufficient solution. Please forget about it.

We also need to think of what should happen if all of the nameservers return ServFail (This is the expected result when the record set has a bogus DNSSEC signature).
In that case, the control goes to

timeout_error = true
and a timeout error is raised, which might not be a desired behavior. This means that to handle ServFail correctly, the error needs to be notified to ‎Resolv::DNS::Config#resolv, which conducts retrying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resolv cannot resolve address if resolv.conf first nameserver answers with SERVFAIL

3 participants