mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-10-12 01:58:46 +02:00
fix(cli): mark AD lookups on the bypass and OS retry paths
The previous change marked a rule-matched AD query as a LAN query, but
two paths still reach the OS resolver without that mark, so osResolver
raced the domain controller against 76.76.2.0 in plaintext:
- the DNS-intercept recovery bypass, which forwards queries before
rule handling runs
- the OS-resolver retry catch-all after an explicit upstream fails
with leak_on_upstream_failure enabled
Mark a query under the detected AD domain on both paths. Other names
keep the public fallback, and an explicit upstream is still tried first.
Build resolvers in queryUpstream() through newResolverFn, so tests drive proxy()
and assert the LAN mark that reaches each resolver, instead of testing
the predicate alone.
This commit is contained in:
4 files changed
+176
-3
No files matched your search
+16
-2
@@ -765,7 +765,15 @@ func (p *prog) proxy(ctx context.Context, req *proxyRequest) *proxyResponse {
|
||||
// general DNS failure does not authorize disclosing private names to DHCP DNS.
|
||||
if dnsIntercept && p.recoveryBypass.Load() && !internalDomainExplicitUpstreams(req.ufr.upstreams) {
|
||||
ctrld.Log(ctx, p.Debug(), "Recovery bypass active: forwarding to OS resolver")
|
||||
answer := p.queryUpstream(ctx, req, upstreamOS, osUpstreamConfig)
|
||||
// The bypass runs before rule handling, so an Active Directory name
|
||||
// needs its LAN mark here too, or it races the domain controller
|
||||
// against Control D's public resolver in plaintext.
|
||||
bypassCtx := ctx
|
||||
if len(req.msg.Question) > 0 && inActiveDirectoryDomain(req.msg.Question[0].Name) {
|
||||
bypassCtx = ctrld.LanQueryCtx(ctx)
|
||||
ctrld.Log(ctx, p.Debug(), "Active Directory domain lookup, skipping public DNS")
|
||||
}
|
||||
answer := p.queryUpstream(bypassCtx, req, upstreamOS, osUpstreamConfig)
|
||||
if answer != nil {
|
||||
return &proxyResponse{answer: answer, upstream: osUpstreamConfig.Endpoint}
|
||||
}
|
||||
@@ -1201,7 +1209,7 @@ func (p *prog) queryUpstream(ctx context.Context, req *proxyRequest, upstream st
|
||||
}
|
||||
|
||||
ctrld.Log(ctx, p.Debug(), "Sending query to %s: %s", upstream, upstreamConfig.Name)
|
||||
dnsResolver, err := ctrld.NewResolver(ctx, upstreamConfig)
|
||||
dnsResolver, err := newResolverFn(ctx, upstreamConfig)
|
||||
if err != nil {
|
||||
ctrld.Log(ctx, p.Error().Err(err), "Failed to create resolver")
|
||||
return nil
|
||||
@@ -1274,6 +1282,12 @@ func (p *prog) triggerRecovery(isOSFailure bool) {
|
||||
// Logs success or failure of the query attempt and returns a proxyResponse or nil based on query result.
|
||||
func (p *prog) tryOSResolver(ctx context.Context, req *proxyRequest) *proxyResponse {
|
||||
ctrld.Log(ctx, p.Debug(), "Attempting query to OS resolver as a retry catch all")
|
||||
// An Active Directory name that falls back from its explicit
|
||||
// upstream still must not reach Control D's public resolver.
|
||||
if len(req.msg.Question) > 0 && inActiveDirectoryDomain(req.msg.Question[0].Name) {
|
||||
ctx = ctrld.LanQueryCtx(ctx)
|
||||
ctrld.Log(ctx, p.Debug(), "Active Directory domain lookup, skipping public DNS")
|
||||
}
|
||||
answer := p.queryUpstream(ctx, req, upstreamOS, osUpstreamConfig)
|
||||
if answer != nil {
|
||||
ctrld.Log(ctx, p.Debug(), "OS resolver retry query successful")
|
||||
|
||||
Reference in new issue
Block a user