Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle RCode::ServFail from nameserver response #26

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

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?

lib/resolv.rb Outdated Show resolved Hide resolved
@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
Development

Successfully merging this pull request may close these issues.

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