Skip to content

Keep the last forwarded response when a fallback is unreachable - #3420

Closed
Dv2Corn wants to merge 1 commit into
DNSCrypt:masterfrom
Dv2Corn:fix/forward-keep-last-response
Closed

Dv2Corn wants to merge 1 commit into
DNSCrypt:masterfrom
Dv2Corn:fix/forward-keep-last-response

Conversation

@Dv2Corn

@Dv2Corn Dv2Corn commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

With a forwarding rule such as lan 192.168.1.1,$BOOTSTRAP, a name that does not exist on 192.168.1.1 gets no answer at all when the bootstrap resolvers cannot be reached: the client times out instead of receiving the NXDOMAIN returned by the first server. The same happens with $DHCP or $RESOLVCONF servers that are down, and with REFUSED and NOTAUTH responses.

After one of these responses, the plugin stores it and tries the next entry of the sequence, so that the last response is returned if nothing better comes (a143fb0): plugin_forward.go#L442-L450. But when the next exchange fails, err is set and the loop ends with return err, and a plugin error makes ApplyQueryPlugins drop the query. The stored response is now returned in that case. The error is still returned when no server answered.

Tested with a new unit test (a local UDP server answering NXDOMAIN, followed by $BOOTSTRAP pointing to a closed port: fails before with connection refused; go test and go vet pass after), and with the built proxy in offline mode and the rule test 127.0.0.1:5301,$BOOTSTRAP: a missing name gets no response before (the client times out) and NXDOMAIN after; names that exist are answered in both cases.

When a server answered NXDOMAIN, REFUSED or NOTAUTH, the next entry of
the sequence is tried and the response is kept in case nothing better
comes. But if that next entry failed with a network error, the error
was returned and the query was dropped instead.
@jedisct1

Copy link
Copy Markdown
Member

Thanks for the PR.

But I prefer to keep the current intentional behavior.

After a negative response, the next entries are there to confirm or to correct it. This is what makes split-horizon rules work.

If a fallback doesn't respond, we don't know if the name exists: returning NXDOMAIN could then be wrong, and clients cache it.
With no response, the client retries and gets the correct answer.

@jedisct1 jedisct1 closed this Nov 12, 2026
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.

2 participants