mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-16 13:17:19 +02:00
fix: wrong DoQ resolver rewriting upstream responses with SetReply
The DoQ resolver called SetReply on the already-unpacked upstream response. SetReply is meant to build a reply from a request, so it forces the RCODE to NOERROR and overwrites the Question with the request's question. This masked upstream failures from the proxy's failover logic (a SERVFAIL looked like a successful empty response) and corrupted the Question section of the response served to clients. Restore only the downstream transaction ID instead (RFC 9250 section 4.2.1 puts the DNS Message ID at 0 on the wire), preserving the upstream RCODE, Question, and answer sections untouched. This matches how the DoH and DoT resolvers return unpacked upstream responses. Refs github.com/Control-D-Inc/ctrld/issues/322
This commit is contained in:
@@ -251,7 +251,15 @@ func (p *doqConnPool) doResolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, er
|
||||
if err := answer.Unpack(buf[2 : 2+respLen]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
answer.SetReply(msg)
|
||||
// RFC 9250 section 4.2.1 requires the DNS Message ID to be 0 on the wire,
|
||||
// so restore the downstream transaction ID for the client. Do NOT use
|
||||
// SetReply here: it rewrites the RCODE to NOERROR and overwrites the
|
||||
// Question with the request's, which would mask upstream failures from the
|
||||
// failover logic (a SERVFAIL would look like success) and let a
|
||||
// wrong-question answer pass validation and poison the cache. Preserve the
|
||||
// upstream RCODE, Question, and answer sections untouched so the proxy can
|
||||
// evaluate them. See github.com/Control-D-Inc/ctrld/issues/322.
|
||||
answer.Id = msg.Id
|
||||
return answer, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user